From 2de9548c23fe8fe7ad4a88dcbb4f87b2c7068683 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Sun, 7 Jun 2020 22:12:04 +0700 Subject: [PATCH 001/393] Implement commons-rng particle in pure Kotlin --- kmath-commons-rng-part/build.gradle.kts | 2 + .../commons/rng/UniformRandomProvider.kt | 19 ++ .../rng/sampling/SharedStateSampler.kt | 7 + .../AhrensDieterExponentialSampler.kt | 95 +++++++ .../BoxMullerNormalizedGaussianSampler.kt | 50 ++++ .../distribution/ContinuousSampler.kt | 5 + .../sampling/distribution/DiscreteSampler.kt | 5 + .../sampling/distribution/GaussianSampler.kt | 45 ++++ .../sampling/distribution/InternalGamma.kt | 43 ++++ .../sampling/distribution/InternalUtils.kt | 92 +++++++ .../KempSmallMeanPoissonSampler.kt | 56 +++++ .../distribution/LargenMeanPoissonSampler.kt | 233 ++++++++++++++++++ .../MarsagliaNormalizedGaussianSampler.kt | 54 ++++ .../distribution/NormalizedGaussianSampler.kt | 3 + .../sampling/distribution/PoissonSampler.kt | 32 +++ .../rng/sampling/distribution/SamplerBase.kt | 12 + .../SharedStateContinuousSampler.kt | 7 + .../SharedStateDiscreteSampler.kt | 7 + .../distribution/SmallMeanPoissonSampler.kt | 58 +++++ .../ZigguratNormalizedGaussianSampler.kt | 89 +++++++ kmath-prob/build.gradle.kts | 6 +- .../scientifik/kmath/prob/Distributions.kt | 53 ++++ .../kmath/prob/RandomSourceGenerator.kt | 28 +++ .../scientifik/kmath/prob/Distributions.kt | 62 +++++ .../kmath/prob/RandomSourceGenerator.kt | 50 ++-- .../scientifik/kmath/prob/distributions.kt | 109 -------- settings.gradle.kts | 1 + 27 files changed, 1078 insertions(+), 145 deletions(-) create mode 100644 kmath-commons-rng-part/build.gradle.kts create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/UniformRandomProvider.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/SharedStateSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ContinuousSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/DiscreteSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/GaussianSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalGamma.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalUtils.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/PoissonSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SamplerBase.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt create mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distributions.kt create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt create mode 100644 kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/Distributions.kt delete mode 100644 kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt diff --git a/kmath-commons-rng-part/build.gradle.kts b/kmath-commons-rng-part/build.gradle.kts new file mode 100644 index 000000000..9d3cd0e7d --- /dev/null +++ b/kmath-commons-rng-part/build.gradle.kts @@ -0,0 +1,2 @@ +plugins { id("scientifik.mpp") } +kotlin.sourceSets { commonMain.get().dependencies { api(project(":kmath-coroutines")) } } diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/UniformRandomProvider.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/UniformRandomProvider.kt new file mode 100644 index 000000000..2fbf7a0a2 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/UniformRandomProvider.kt @@ -0,0 +1,19 @@ +package scientifik.commons.rng + +interface UniformRandomProvider { + fun nextBytes(bytes: ByteArray) + + fun nextBytes( + bytes: ByteArray, + start: Int, + len: Int + ) + + fun nextInt(): Int + fun nextInt(n: Int): Int + fun nextLong(): Long + fun nextLong(n: Long): Long + fun nextBoolean(): Boolean + fun nextFloat(): Float + fun nextDouble(): Double +} \ No newline at end of file diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/SharedStateSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/SharedStateSampler.kt new file mode 100644 index 000000000..d32a646c2 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/SharedStateSampler.kt @@ -0,0 +1,7 @@ +package scientifik.commons.rng.sampling + +import scientifik.commons.rng.UniformRandomProvider + +interface SharedStateSampler { + fun withUniformRandomProvider(rng: UniformRandomProvider): R +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt new file mode 100644 index 000000000..7aa061951 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt @@ -0,0 +1,95 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.UniformRandomProvider +import kotlin.math.ln +import kotlin.math.pow + +class AhrensDieterExponentialSampler : SamplerBase, + SharedStateContinuousSampler { + private val mean: Double + private val rng: UniformRandomProvider + + constructor( + rng: UniformRandomProvider, + mean: Double + ) : super(null) { + require(mean > 0) { "mean is not strictly positive: $mean" } + this.rng = rng + this.mean = mean + } + + private constructor( + rng: UniformRandomProvider, + source: AhrensDieterExponentialSampler + ) : super(null) { + this.rng = rng + mean = source.mean + } + + override fun sample(): Double { + // Step 1: + var a = 0.0 + var u: Double = rng.nextDouble() + + // Step 2 and 3: + while (u < 0.5) { + a += EXPONENTIAL_SA_QI.get( + 0 + ) + u *= 2.0 + } + + // Step 4 (now u >= 0.5): + u += u - 1 + + // Step 5: + if (u <= EXPONENTIAL_SA_QI.get( + 0 + ) + ) { + return mean * (a + u) + } + + // Step 6: + var i = 0 // Should be 1, be we iterate before it in while using 0. + var u2: Double = rng.nextDouble() + var umin = u2 + + // Step 7 and 8: + do { + ++i + u2 = rng.nextDouble() + if (u2 < umin) umin = u2 + // Step 8: + } while (u > EXPONENTIAL_SA_QI[i]) // Ensured to exit since EXPONENTIAL_SA_QI[MAX] = 1. + return mean * (a + umin * EXPONENTIAL_SA_QI[0]) + } + + override fun toString(): String = "Ahrens-Dieter Exponential deviate [$rng]" + + override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateContinuousSampler = + AhrensDieterExponentialSampler(rng, this) + + companion object { + private val EXPONENTIAL_SA_QI = DoubleArray(16) + + fun of( + rng: UniformRandomProvider, + mean: Double + ): SharedStateContinuousSampler = AhrensDieterExponentialSampler(rng, mean) + + init { + /** + * Filling EXPONENTIAL_SA_QI table. + * Note that we don't want qi = 0 in the table. + */ + val ln2 = ln(2.0) + var qi = 0.0 + + EXPONENTIAL_SA_QI.indices.forEach { i -> + qi += ln2.pow(i + 1.0) / InternalUtils.factorial(i + 1) + EXPONENTIAL_SA_QI[i] = qi + } + } + } +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt new file mode 100644 index 000000000..91b3314b5 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt @@ -0,0 +1,50 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.UniformRandomProvider +import kotlin.math.* + +class BoxMullerNormalizedGaussianSampler( + private val rng: UniformRandomProvider +) : + NormalizedGaussianSampler, + SharedStateContinuousSampler { + private var nextGaussian: Double = Double.NaN + + override fun sample(): Double { + val random: Double + + if (nextGaussian.isNaN()) { + // Generate a pair of Gaussian numbers. + val x = rng.nextDouble() + val y = rng.nextDouble() + val alpha = 2 * PI * x + val r = sqrt(-2 * ln(y)) + + // Return the first element of the generated pair. + random = r * cos(alpha) + + // Keep second element of the pair for next invocation. + nextGaussian = r * sin(alpha) + } else { + // Use the second element of the pair (generated at the + // previous invocation). + random = nextGaussian + + // Both elements of the pair have been used. + nextGaussian = Double.NaN + } + + return random + } + + override fun toString(): String = "Box-Muller normalized Gaussian deviate [$rng]" + + override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateContinuousSampler = + BoxMullerNormalizedGaussianSampler(rng) + + companion object { + @Suppress("UNCHECKED_CAST") + fun of(rng: UniformRandomProvider): S where S : NormalizedGaussianSampler?, S : SharedStateContinuousSampler? = + BoxMullerNormalizedGaussianSampler(rng) as S + } +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ContinuousSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ContinuousSampler.kt new file mode 100644 index 000000000..4841672a2 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ContinuousSampler.kt @@ -0,0 +1,5 @@ +package scientifik.commons.rng.sampling.distribution + +interface ContinuousSampler { + fun sample(): Double +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/DiscreteSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/DiscreteSampler.kt new file mode 100644 index 000000000..8e8bccd18 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/DiscreteSampler.kt @@ -0,0 +1,5 @@ +package scientifik.commons.rng.sampling.distribution + +interface DiscreteSampler { + fun sample(): Int +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/GaussianSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/GaussianSampler.kt new file mode 100644 index 000000000..424ea90fe --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/GaussianSampler.kt @@ -0,0 +1,45 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.UniformRandomProvider + +class GaussianSampler : SharedStateContinuousSampler { + private val mean: Double + private val standardDeviation: Double + private val normalized: NormalizedGaussianSampler + + constructor( + normalized: NormalizedGaussianSampler, + mean: Double, + standardDeviation: Double + ) { + require(standardDeviation > 0) { "standard deviation is not strictly positive: $standardDeviation" } + this.normalized = normalized + this.mean = mean + this.standardDeviation = standardDeviation + } + + private constructor( + rng: UniformRandomProvider, + source: GaussianSampler + ) { + mean = source.mean + standardDeviation = source.standardDeviation + normalized = InternalUtils.newNormalizedGaussianSampler(source.normalized, rng) + } + + override fun sample(): Double = standardDeviation * normalized.sample() + mean + + override fun toString(): String = "Gaussian deviate [$normalized]" + + override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateContinuousSampler { + return GaussianSampler(rng, this) + } + + companion object { + fun of( + normalized: NormalizedGaussianSampler, + mean: Double, + standardDeviation: Double + ): SharedStateContinuousSampler = GaussianSampler(normalized, mean, standardDeviation) + } +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalGamma.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalGamma.kt new file mode 100644 index 000000000..a75ba1608 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalGamma.kt @@ -0,0 +1,43 @@ +package scientifik.commons.rng.sampling.distribution + +import kotlin.math.PI +import kotlin.math.ln + +internal object InternalGamma { + const val LANCZOS_G = 607.0 / 128.0 + + private val LANCZOS_COEFFICIENTS = doubleArrayOf( + 0.99999999999999709182, + 57.156235665862923517, + -59.597960355475491248, + 14.136097974741747174, + -0.49191381609762019978, + .33994649984811888699e-4, + .46523628927048575665e-4, + -.98374475304879564677e-4, + .15808870322491248884e-3, + -.21026444172410488319e-3, + .21743961811521264320e-3, + -.16431810653676389022e-3, + .84418223983852743293e-4, + -.26190838401581408670e-4, + .36899182659531622704e-5 + ) + + private val HALF_LOG_2_PI: Double = 0.5 * ln(2.0 * PI) + + fun logGamma(x: Double): Double { + // Stripped-down version of the same method defined in "Commons Math": + // Unused "if" branches (for when x < 8) have been removed here since + // this method is only used (by class "InternalUtils") in order to + // compute log(n!) for x > 20. + val sum = lanczos(x) + val tmp = x + LANCZOS_G + 0.5 + return (x + 0.5) * ln(tmp) - tmp + HALF_LOG_2_PI + ln(sum / x) + } + + private fun lanczos(x: Double): Double { + val sum = (LANCZOS_COEFFICIENTS.size - 1 downTo 1).sumByDouble { LANCZOS_COEFFICIENTS[it] / (x + it) } + return sum + LANCZOS_COEFFICIENTS[0] + } +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalUtils.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalUtils.kt new file mode 100644 index 000000000..8134252aa --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalUtils.kt @@ -0,0 +1,92 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.UniformRandomProvider +import scientifik.commons.rng.sampling.SharedStateSampler +import kotlin.math.ln +import kotlin.math.min + +internal object InternalUtils { + private val FACTORIALS = longArrayOf( + 1L, 1L, 2L, + 6L, 24L, 120L, + 720L, 5040L, 40320L, + 362880L, 3628800L, 39916800L, + 479001600L, 6227020800L, 87178291200L, + 1307674368000L, 20922789888000L, 355687428096000L, + 6402373705728000L, 121645100408832000L, 2432902008176640000L + ) + + private const val BEGIN_LOG_FACTORIALS = 2 + + fun factorial(n: Int): Long = FACTORIALS[n] + + fun validateProbabilities(probabilities: DoubleArray?): Double { + require(!(probabilities == null || probabilities.isEmpty())) { "Probabilities must not be empty." } + var sumProb = 0.0 + + probabilities.forEach { prob -> + validateProbability(prob) + sumProb += prob + } + + require(!(sumProb.isInfinite() || sumProb <= 0)) { "Invalid sum of probabilities: $sumProb" } + return sumProb + } + + fun validateProbability(probability: Double): Unit = + require(!(probability < 0 || probability.isInfinite() || probability.isNaN())) { "Invalid probability: $probability" } + + fun newNormalizedGaussianSampler( + sampler: NormalizedGaussianSampler, + rng: UniformRandomProvider + ): NormalizedGaussianSampler { + if (sampler !is SharedStateSampler<*>) throw UnsupportedOperationException("The underlying sampler cannot share state") + + val newSampler: Any = + (sampler as SharedStateSampler<*>).withUniformRandomProvider(rng) as? NormalizedGaussianSampler + ?: throw UnsupportedOperationException( + "The underlying sampler did not create a normalized Gaussian sampler" + ) + + return newSampler as NormalizedGaussianSampler + } + + class FactorialLog private constructor( + numValues: Int, + cache: DoubleArray? + ) { + private val logFactorials: DoubleArray = DoubleArray(numValues) + + init { + val endCopy: Int + + if (cache != null && cache.size > BEGIN_LOG_FACTORIALS) { + // Copy available values. + endCopy = min(cache.size, numValues) + cache.copyInto(logFactorials, BEGIN_LOG_FACTORIALS, BEGIN_LOG_FACTORIALS, endCopy) + } + // All values to be computed + else + endCopy = BEGIN_LOG_FACTORIALS + + // Compute remaining values. + (endCopy until numValues).forEach { i -> + if (i < FACTORIALS.size) logFactorials[i] = ln(FACTORIALS[i].toDouble()) else logFactorials[i] = + logFactorials[i - 1] + ln(i.toDouble()) + } + } + + fun withCache(cacheSize: Int): FactorialLog = FactorialLog(cacheSize, logFactorials) + + fun value(n: Int): Double { + if (n < logFactorials.size) + return logFactorials[n] + + return if (n < FACTORIALS.size) ln(FACTORIALS[n].toDouble()) else InternalGamma.logGamma(n + 1.0) + } + + companion object { + fun create(): FactorialLog = FactorialLog(0, null) + } + } +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt new file mode 100644 index 000000000..6501089b2 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt @@ -0,0 +1,56 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.UniformRandomProvider +import kotlin.math.exp + +class KempSmallMeanPoissonSampler private constructor( + private val rng: UniformRandomProvider, + private val p0: Double, + private val mean: Double +) : SharedStateDiscreteSampler { + override fun sample(): Int { + // Note on the algorithm: + // - X is the unknown sample deviate (the output of the algorithm) + // - x is the current value from the distribution + // - p is the probability of the current value x, p(X=x) + // - u is effectively the cumulative probability that the sample X + // is equal or above the current value x, p(X>=x) + // So if p(X>=x) > p(X=x) the sample must be above x, otherwise it is x + var u = rng.nextDouble() + var x = 0 + var p = p0 + + while (u > p) { + u -= p + // Compute the next probability using a recurrence relation. + // p(x+1) = p(x) * mean / (x+1) + p *= mean / ++x + // The algorithm listed in Kemp (1981) does not check that the rolling probability + // is positive. This check is added to ensure no errors when the limit of the summation + // 1 - sum(p(x)) is above 0 due to cumulative error in floating point arithmetic. + if (p == 0.0) return x + } + + return x + } + + override fun toString(): String = "Kemp Small Mean Poisson deviate [$rng]" + + override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateDiscreteSampler = + KempSmallMeanPoissonSampler(rng, p0, mean) + + companion object { + fun of( + rng: UniformRandomProvider, + mean: Double + ): SharedStateDiscreteSampler { + require(mean > 0) { "Mean is not strictly positive: $mean" } + val p0: Double = exp(-mean) + + // Probability must be positive. As mean increases then p(0) decreases. + if (p0 > 0) return KempSmallMeanPoissonSampler(rng, p0, mean) + throw IllegalArgumentException("No probability for mean: $mean") + } + } +} + diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt new file mode 100644 index 000000000..ce1e1e3b0 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt @@ -0,0 +1,233 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.UniformRandomProvider +import kotlin.math.* + +class LargeMeanPoissonSampler : SharedStateDiscreteSampler { + private val rng: UniformRandomProvider + private val exponential: SharedStateContinuousSampler + private val gaussian: SharedStateContinuousSampler + private val factorialLog: InternalUtils.FactorialLog + private val lambda: Double + private val logLambda: Double + private val logLambdaFactorial: Double + private val delta: Double + private val halfDelta: Double + private val twolpd: Double + private val p1: Double + private val p2: Double + private val c1: Double + private val smallMeanPoissonSampler: SharedStateDiscreteSampler + + constructor( + rng: UniformRandomProvider, + mean: Double + ) { + require(mean >= 1) { "mean is not >= 1: $mean" } + // The algorithm is not valid if Math.floor(mean) is not an integer. + require(mean <= MAX_MEAN) { "mean $mean > $MAX_MEAN" } + this.rng = rng + gaussian = ZigguratNormalizedGaussianSampler(rng) + exponential = AhrensDieterExponentialSampler.of(rng, 1.0) + // Plain constructor uses the uncached function. + factorialLog = NO_CACHE_FACTORIAL_LOG!! + // Cache values used in the algorithm + lambda = floor(mean) + logLambda = ln(lambda) + logLambdaFactorial = getFactorialLog(lambda.toInt()) + delta = sqrt(lambda * ln(32 * lambda / PI + 1)) + halfDelta = delta / 2 + twolpd = 2 * lambda + delta + c1 = 1 / (8 * lambda) + val a1: Double = sqrt(PI * twolpd) * exp(c1) + val a2: Double = twolpd / delta * exp(-delta * (1 + delta) / twolpd) + val aSum = a1 + a2 + 1 + p1 = a1 / aSum + p2 = a2 / aSum + + // The algorithm requires a Poisson sample from the remaining lambda fraction. + val lambdaFractional = mean - lambda + smallMeanPoissonSampler = + if (lambdaFractional < Double.MIN_VALUE) NO_SMALL_MEAN_POISSON_SAMPLER else // Not used. + KempSmallMeanPoissonSampler.of(rng, lambdaFractional) + } + + internal constructor( + rng: UniformRandomProvider, + state: LargeMeanPoissonSamplerState, + lambdaFractional: Double + ) { + require(!(lambdaFractional < 0 || lambdaFractional >= 1)) { "lambdaFractional must be in the range 0 (inclusive) to 1 (exclusive): $lambdaFractional" } + this.rng = rng + gaussian = ZigguratNormalizedGaussianSampler(rng) + exponential = AhrensDieterExponentialSampler.of(rng, 1.0) + // Plain constructor uses the uncached function. + factorialLog = NO_CACHE_FACTORIAL_LOG!! + // Use the state to initialise the algorithm + lambda = state.lambdaRaw + logLambda = state.logLambda + logLambdaFactorial = state.logLambdaFactorial + delta = state.delta + halfDelta = state.halfDelta + twolpd = state.twolpd + p1 = state.p1 + p2 = state.p2 + c1 = state.c1 + + // The algorithm requires a Poisson sample from the remaining lambda fraction. + smallMeanPoissonSampler = + if (lambdaFractional < Double.MIN_VALUE) + NO_SMALL_MEAN_POISSON_SAMPLER + else // Not used. + KempSmallMeanPoissonSampler.of(rng, lambdaFractional) + } + + /** + * @param rng Generator of uniformly distributed random numbers. + * @param source Source to copy. + */ + private constructor( + rng: UniformRandomProvider, + source: LargeMeanPoissonSampler + ) { + this.rng = rng + gaussian = source.gaussian.withUniformRandomProvider(rng)!! + exponential = source.exponential.withUniformRandomProvider(rng)!! + // Reuse the cache + factorialLog = source.factorialLog + lambda = source.lambda + logLambda = source.logLambda + logLambdaFactorial = source.logLambdaFactorial + delta = source.delta + halfDelta = source.halfDelta + twolpd = source.twolpd + p1 = source.p1 + p2 = source.p2 + c1 = source.c1 + + // Share the state of the small sampler + smallMeanPoissonSampler = source.smallMeanPoissonSampler.withUniformRandomProvider(rng)!! + } + + /** {@inheritDoc} */ + override fun sample(): Int { + // This will never be null. It may be a no-op delegate that returns zero. + val y2: Int = smallMeanPoissonSampler.sample() + var x: Double + var y: Double + var v: Double + var a: Int + var t: Double + var qr: Double + var qa: Double + while (true) { + // Step 1: + val u = rng.nextDouble() + + if (u <= p1) { + // Step 2: + val n = gaussian.sample() + x = n * sqrt(lambda + halfDelta) - 0.5 + if (x > delta || x < -lambda) continue + y = if (x < 0) floor(x) else ceil(x) + val e = exponential.sample() + v = -e - 0.5 * n * n + c1 + } else { + // Step 3: + if (u > p1 + p2) { + y = lambda + break + } + + x = delta + twolpd / delta * exponential.sample() + y = ceil(x) + v = -exponential.sample() - delta * (x + 1) / twolpd + } + // The Squeeze Principle + // Step 4.1: + a = if (x < 0) 1 else 0 + t = y * (y + 1) / (2 * lambda) + + // Step 4.2 + if (v < -t && a == 0) { + y += lambda + break + } + + // Step 4.3: + qr = t * ((2 * y + 1) / (6 * lambda) - 1) + qa = qr - t * t / (3 * (lambda + a * (y + 1))) + + // Step 4.4: + if (v < qa) { + y += lambda + break + } + + // Step 4.5: + if (v > qr) continue + + // Step 4.6: + if (v < y * logLambda - getFactorialLog((y + lambda).toInt()) + logLambdaFactorial) { + y += lambda + break + } + } + + return min(y2 + y.toLong(), Int.MAX_VALUE.toLong()).toInt() + } + + + private fun getFactorialLog(n: Int): Double = factorialLog.value(n) + + override fun toString(): String = "Large Mean Poisson deviate [$rng]" + + override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateDiscreteSampler = + LargeMeanPoissonSampler(rng, this) + + val state: LargeMeanPoissonSamplerState + get() = LargeMeanPoissonSamplerState( + lambda, logLambda, logLambdaFactorial, + delta, halfDelta, twolpd, p1, p2, c1 + ) + + class LargeMeanPoissonSamplerState( + val lambdaRaw: Double, + val logLambda: Double, + val logLambdaFactorial: Double, + val delta: Double, + val halfDelta: Double, + val twolpd: Double, + val p1: Double, + val p2: Double, + val c1: Double + ) { + fun getLambda(): Int = lambdaRaw.toInt() + } + + companion object { + private const val MAX_MEAN = 0.5 * Int.MAX_VALUE + private var NO_CACHE_FACTORIAL_LOG: InternalUtils.FactorialLog? = null + + private val NO_SMALL_MEAN_POISSON_SAMPLER: SharedStateDiscreteSampler = + object : SharedStateDiscreteSampler { + override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateDiscreteSampler = +// No requirement for RNG + this + + override fun sample(): Int =// No Poisson sample + 0 + } + + fun of( + rng: UniformRandomProvider, + mean: Double + ): SharedStateDiscreteSampler = LargeMeanPoissonSampler(rng, mean) + + init { + // Create without a cache. + NO_CACHE_FACTORIAL_LOG = + InternalUtils.FactorialLog.create() + } + } +} \ No newline at end of file diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt new file mode 100644 index 000000000..26ee9ece9 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt @@ -0,0 +1,54 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.UniformRandomProvider +import kotlin.math.ln +import kotlin.math.sqrt + +class MarsagliaNormalizedGaussianSampler(private val rng: UniformRandomProvider) : + NormalizedGaussianSampler, + SharedStateContinuousSampler { + private var nextGaussian = Double.NaN + + override fun sample(): Double { + if (nextGaussian.isNaN()) { + // Rejection scheme for selecting a pair that lies within the unit circle. + while (true) { + // Generate a pair of numbers within [-1 , 1). + val x = 2.0 * rng.nextDouble() - 1.0 + val y = 2.0 * rng.nextDouble() - 1.0 + val r2 = x * x + y * y + if (r2 < 1 && r2 > 0) { + // Pair (x, y) is within unit circle. + val alpha = sqrt(-2 * ln(r2) / r2) + + // Keep second element of the pair for next invocation. + nextGaussian = alpha * y + + // Return the first element of the generated pair. + return alpha * x + } + + // Pair is not within the unit circle: Generate another one. + } + } else { + // Use the second element of the pair (generated at the + // previous invocation). + val r = nextGaussian + + // Both elements of the pair have been used. + nextGaussian = Double.NaN + return r + } + } + + override fun toString(): String = "Box-Muller (with rejection) normalized Gaussian deviate [$rng]" + + override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateContinuousSampler = + MarsagliaNormalizedGaussianSampler(rng) + + companion object { + @Suppress("UNCHECKED_CAST") + fun of(rng: UniformRandomProvider): S where S : NormalizedGaussianSampler?, S : SharedStateContinuousSampler? = + MarsagliaNormalizedGaussianSampler(rng) as S + } +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt new file mode 100644 index 000000000..feff4d954 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt @@ -0,0 +1,3 @@ +package scientifik.commons.rng.sampling.distribution + +interface NormalizedGaussianSampler : ContinuousSampler diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/PoissonSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/PoissonSampler.kt new file mode 100644 index 000000000..4a7f56f60 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/PoissonSampler.kt @@ -0,0 +1,32 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.UniformRandomProvider + +class PoissonSampler( + rng: UniformRandomProvider, + mean: Double +) : SamplerBase(null), SharedStateDiscreteSampler { + private val poissonSamplerDelegate: SharedStateDiscreteSampler + + override fun sample(): Int = poissonSamplerDelegate.sample() + override fun toString(): String = poissonSamplerDelegate.toString() + + override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateDiscreteSampler? = +// Direct return of the optimised sampler + poissonSamplerDelegate.withUniformRandomProvider(rng) + + companion object { + const val PIVOT = 40.0 + + fun of( + rng: UniformRandomProvider, + mean: Double + ): SharedStateDiscreteSampler =// Each sampler should check the input arguments. + if (mean < PIVOT) SmallMeanPoissonSampler.of(rng, mean) else LargeMeanPoissonSampler.of(rng, mean) + } + + init { + // Delegate all work to specialised samplers. + poissonSamplerDelegate = of(rng, mean) + } +} \ No newline at end of file diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SamplerBase.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SamplerBase.kt new file mode 100644 index 000000000..38df9eb4e --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SamplerBase.kt @@ -0,0 +1,12 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.UniformRandomProvider + +@Deprecated("Since version 1.1. Class intended for internal use only.") +open class SamplerBase protected constructor(private val rng: UniformRandomProvider?) { + protected fun nextDouble(): Double = rng!!.nextDouble() + protected fun nextInt(): Int = rng!!.nextInt() + protected fun nextInt(max: Int): Int = rng!!.nextInt(max) + protected fun nextLong(): Long = rng!!.nextLong() + override fun toString(): String = "rng=$rng" +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt new file mode 100644 index 000000000..ddac4b7a7 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt @@ -0,0 +1,7 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.sampling.SharedStateSampler + +interface SharedStateContinuousSampler : ContinuousSampler, + SharedStateSampler { +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt new file mode 100644 index 000000000..2d8adada6 --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt @@ -0,0 +1,7 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.sampling.SharedStateSampler + +interface SharedStateDiscreteSampler : DiscreteSampler, + SharedStateSampler { // Composite interface +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt new file mode 100644 index 000000000..a3188620f --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt @@ -0,0 +1,58 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.UniformRandomProvider +import kotlin.math.ceil +import kotlin.math.exp + +class SmallMeanPoissonSampler : SharedStateDiscreteSampler { + private val p0: Double + private val limit: Int + private val rng: UniformRandomProvider + + constructor( + rng: UniformRandomProvider, + mean: Double + ) { + this.rng = rng + require(mean > 0) { "mean is not strictly positive: $mean" } + p0 = exp(-mean) + + limit = (if (p0 > 0) ceil(1000 * mean) else throw IllegalArgumentException("No p(x=0) probability for mean: $mean")).toInt() + // This excludes NaN values for the mean + // else + // The returned sample is bounded by 1000 * mean + } + + private constructor( + rng: UniformRandomProvider, + source: SmallMeanPoissonSampler + ) { + this.rng = rng + p0 = source.p0 + limit = source.limit + } + + override fun sample(): Int { + var n = 0 + var r = 1.0 + + while (n < limit) { + r *= rng.nextDouble() + if (r >= p0) n++ else break + } + + return n + } + + override fun toString(): String = "Small Mean Poisson deviate [$rng]" + + override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateDiscreteSampler = + SmallMeanPoissonSampler(rng, this) + + companion object { + fun of( + rng: UniformRandomProvider, + mean: Double + ): SharedStateDiscreteSampler = SmallMeanPoissonSampler(rng, mean) + } +} \ No newline at end of file diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt new file mode 100644 index 000000000..a916121db --- /dev/null +++ b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt @@ -0,0 +1,89 @@ +package scientifik.commons.rng.sampling.distribution + +import scientifik.commons.rng.UniformRandomProvider +import kotlin.math.* + +class ZigguratNormalizedGaussianSampler(private val rng: UniformRandomProvider) : + NormalizedGaussianSampler, + SharedStateContinuousSampler { + + companion object { + private const val R = 3.442619855899 + private const val ONE_OVER_R: Double = 1 / R + private const val V = 9.91256303526217e-3 + private val MAX: Double = 2.0.pow(63.0) + private val ONE_OVER_MAX: Double = 1.0 / MAX + private const val LEN = 128 + private const val LAST: Int = LEN - 1 + private val K = LongArray(LEN) + private val W = DoubleArray(LEN) + private val F = DoubleArray(LEN) + private fun gauss(x: Double): Double = exp(-0.5 * x * x) + + @Suppress("UNCHECKED_CAST") + fun of(rng: UniformRandomProvider): S where S : NormalizedGaussianSampler?, S : SharedStateContinuousSampler? = + ZigguratNormalizedGaussianSampler(rng) as S + + init { + // Filling the tables. + var d = R + var t = d + var fd = gauss(d) + val q = V / fd + K[0] = (d / q * MAX).toLong() + K[1] = 0 + W[0] = q * ONE_OVER_MAX + W[LAST] = d * ONE_OVER_MAX + F[0] = 1.0 + F[LAST] = fd + + (LAST - 1 downTo 1).forEach { i -> + d = sqrt(-2 * ln(V / d + fd)) + fd = gauss(d) + K[i + 1] = (d / t * MAX).toLong() + t = d + F[i] = fd + W[i] = d * ONE_OVER_MAX + } + } + } + + override fun sample(): Double { + val j = rng.nextLong() + val i = (j and LAST.toLong()).toInt() + return if (abs(j) < K[i]) j * W[i] else fix(j, i) + } + + override fun toString(): String = "Ziggurat normalized Gaussian deviate [$rng]" + + private fun fix( + hz: Long, + iz: Int + ): Double { + var x: Double + var y: Double + x = hz * W[iz] + + return if (iz == 0) { + // Base strip. + // This branch is called about 5.7624515E-4 times per sample. + do { + y = -ln(rng.nextDouble()) + x = -ln(rng.nextDouble()) * ONE_OVER_R + } while (y + y < x * x) + + val out = R + x + if (hz > 0) out else -out + } else { + // Wedge of other strips. + // This branch is called about 0.027323 times per sample. + // else + // Try again. + // This branch is called about 0.012362 times per sample. + if (F[iz] + rng.nextDouble() * (F[iz - 1] - F[iz]) < gauss(x)) x else sample() + } + } + + override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateContinuousSampler = + ZigguratNormalizedGaussianSampler(rng) +} diff --git a/kmath-prob/build.gradle.kts b/kmath-prob/build.gradle.kts index a69d61b73..4ec254e82 100644 --- a/kmath-prob/build.gradle.kts +++ b/kmath-prob/build.gradle.kts @@ -6,10 +6,12 @@ kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-coroutines")) + api(project(":kmath-commons-rng-part")) } } - jvmMain{ - dependencies{ + + jvmMain { + dependencies { api("org.apache.commons:commons-rng-sampling:1.3") api("org.apache.commons:commons-rng-simple:1.3") } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distributions.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distributions.kt new file mode 100644 index 000000000..fd8cc4116 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distributions.kt @@ -0,0 +1,53 @@ +package scientifik.kmath.prob + +import scientifik.commons.rng.UniformRandomProvider +import scientifik.commons.rng.sampling.distribution.* +import scientifik.kmath.chains.BlockingIntChain +import scientifik.kmath.chains.BlockingRealChain +import scientifik.kmath.chains.Chain + +abstract class ContinuousSamplerDistribution : Distribution { + + private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingRealChain() { + private val sampler = buildCMSampler(generator) + + override fun nextDouble(): Double = sampler.sample() + + override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) + } + + protected abstract fun buildCMSampler(generator: RandomGenerator): ContinuousSampler + + override fun sample(generator: RandomGenerator): BlockingRealChain = ContinuousSamplerChain(generator) +} + +abstract class DiscreteSamplerDistribution : Distribution { + + private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingIntChain() { + private val sampler = buildSampler(generator) + + override fun nextInt(): Int = sampler.sample() + + override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) + } + + protected abstract fun buildSampler(generator: RandomGenerator): DiscreteSampler + + override fun sample(generator: RandomGenerator): BlockingIntChain = ContinuousSamplerChain(generator) +} + +enum class NormalSamplerMethod { + BoxMuller, + Marsaglia, + Ziggurat +} + +fun normalSampler(method: NormalSamplerMethod, provider: UniformRandomProvider): NormalizedGaussianSampler = + when (method) { + NormalSamplerMethod.BoxMuller -> BoxMullerNormalizedGaussianSampler( + provider + ) + NormalSamplerMethod.Marsaglia -> MarsagliaNormalizedGaussianSampler(provider) + NormalSamplerMethod.Ziggurat -> ZigguratNormalizedGaussianSampler(provider) + } + diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt new file mode 100644 index 000000000..7be8276f3 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt @@ -0,0 +1,28 @@ +package scientifik.kmath.prob + +import scientifik.commons.rng.UniformRandomProvider + + +inline class RandomGeneratorProvider(val generator: RandomGenerator) : UniformRandomProvider { + override fun nextBoolean(): Boolean = generator.nextBoolean() + + override fun nextFloat(): Float = generator.nextDouble().toFloat() + + override fun nextBytes(bytes: ByteArray) { + generator.fillBytes(bytes) + } + + override fun nextBytes(bytes: ByteArray, start: Int, len: Int) { + generator.fillBytes(bytes, start, start + len) + } + + override fun nextInt(): Int = generator.nextInt() + + override fun nextInt(n: Int): Int = generator.nextInt(n) + + override fun nextDouble(): Double = generator.nextDouble() + + override fun nextLong(): Long = generator.nextLong() + + override fun nextLong(n: Long): Long = generator.nextLong(n) +} diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/Distributions.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/Distributions.kt new file mode 100644 index 000000000..aaeeb1b26 --- /dev/null +++ b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/Distributions.kt @@ -0,0 +1,62 @@ +package scientifik.kmath.prob + +import scientifik.commons.rng.sampling.distribution.ContinuousSampler +import scientifik.commons.rng.sampling.distribution.DiscreteSampler +import scientifik.commons.rng.sampling.distribution.GaussianSampler +import scientifik.commons.rng.sampling.distribution.PoissonSampler +import kotlin.math.PI +import kotlin.math.exp +import kotlin.math.pow +import kotlin.math.sqrt + +fun Distribution.Companion.normal( + method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat +): Distribution = object : ContinuousSamplerDistribution() { + override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler { + val provider = generator.asUniformRandomProvider() + return normalSampler(method, provider) + } + + override fun probability(arg: Double): Double { + return exp(-arg.pow(2) / 2) / sqrt(PI * 2) + } +} + +fun Distribution.Companion.normal( + mean: Double, + sigma: Double, + method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat +): ContinuousSamplerDistribution = object : ContinuousSamplerDistribution() { + private val sigma2 = sigma.pow(2) + private val norm = sigma * sqrt(PI * 2) + + override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler { + val provider = generator.asUniformRandomProvider() + val normalizedSampler = normalSampler(method, provider) + return GaussianSampler(normalizedSampler, mean, sigma) + } + + override fun probability(arg: Double): Double { + return exp(-(arg - mean).pow(2) / 2 / sigma2) / norm + } +} + +fun Distribution.Companion.poisson( + lambda: Double +): DiscreteSamplerDistribution = object : DiscreteSamplerDistribution() { + + override fun buildSampler(generator: RandomGenerator): DiscreteSampler { + return PoissonSampler.of(generator.asUniformRandomProvider(), lambda) + } + + private val computedProb: HashMap = hashMapOf(0 to exp(-lambda)) + + override fun probability(arg: Int): Double { + require(arg >= 0) { "The argument must be >= 0" } + + return if (arg > 40) + exp(-(arg - lambda).pow(2) / 2 / lambda) / sqrt(2 * PI * lambda) + else + computedProb.getOrPut(arg) { probability(arg - 1) * lambda / arg } + } +} diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt index f5a73a08b..8c4b59abb 100644 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt +++ b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt @@ -1,20 +1,18 @@ package scientifik.kmath.prob -import org.apache.commons.rng.UniformRandomProvider import org.apache.commons.rng.simple.RandomSource +import scientifik.commons.rng.UniformRandomProvider -class RandomSourceGenerator(val source: RandomSource, seed: Long?) : RandomGenerator { - internal val random: UniformRandomProvider = seed?.let { +class RandomSourceGenerator(val source: RandomSource, seed: Long?) : + RandomGenerator { + internal val random = seed?.let { RandomSource.create(source, seed) } ?: RandomSource.create(source) override fun nextBoolean(): Boolean = random.nextBoolean() - override fun nextDouble(): Double = random.nextDouble() - override fun nextInt(): Int = random.nextInt() override fun nextInt(until: Int): Int = random.nextInt(until) - override fun nextLong(): Long = random.nextLong() override fun nextLong(until: Long): Long = random.nextLong(until) @@ -26,39 +24,23 @@ class RandomSourceGenerator(val source: RandomSource, seed: Long?) : RandomGener override fun fork(): RandomGenerator = RandomSourceGenerator(source, nextLong()) } -inline class RandomGeneratorProvider(val generator: RandomGenerator) : UniformRandomProvider { - override fun nextBoolean(): Boolean = generator.nextBoolean() - - override fun nextFloat(): Float = generator.nextDouble().toFloat() - - override fun nextBytes(bytes: ByteArray) { - generator.fillBytes(bytes) - } - - override fun nextBytes(bytes: ByteArray, start: Int, len: Int) { - generator.fillBytes(bytes, start, start + len) - } - - override fun nextInt(): Int = generator.nextInt() - - override fun nextInt(n: Int): Int = generator.nextInt(n) - - override fun nextDouble(): Double = generator.nextDouble() - - override fun nextLong(): Long = generator.nextLong() - - override fun nextLong(n: Long): Long = generator.nextLong(n) -} - /** * Represent this [RandomGenerator] as commons-rng [UniformRandomProvider] preserving and mirroring its current state. * Getting new value from one of those changes the state of another. */ fun RandomGenerator.asUniformRandomProvider(): UniformRandomProvider = if (this is RandomSourceGenerator) { - random -} else { - RandomGeneratorProvider(this) -} + object : UniformRandomProvider { + override fun nextBytes(bytes: ByteArray) = random.nextBytes(bytes) + override fun nextBytes(bytes: ByteArray, start: Int, len: Int) = random.nextBytes(bytes, start, len) + override fun nextInt(): Int = random.nextInt() + override fun nextInt(n: Int): Int = random.nextInt(n) + override fun nextLong(): Long = random.nextLong() + override fun nextLong(n: Long): Long = random.nextLong(n) + override fun nextBoolean(): Boolean = random.nextBoolean() + override fun nextFloat(): Float = random.nextFloat() + override fun nextDouble(): Double = random.nextDouble() + } +} else RandomGeneratorProvider(this) fun RandomGenerator.Companion.fromSource(source: RandomSource, seed: Long? = null): RandomSourceGenerator = RandomSourceGenerator(source, seed) diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt deleted file mode 100644 index 412454994..000000000 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/distributions.kt +++ /dev/null @@ -1,109 +0,0 @@ -package scientifik.kmath.prob - -import org.apache.commons.rng.UniformRandomProvider -import org.apache.commons.rng.sampling.distribution.* -import scientifik.kmath.chains.BlockingIntChain -import scientifik.kmath.chains.BlockingRealChain -import scientifik.kmath.chains.Chain -import java.util.* -import kotlin.math.PI -import kotlin.math.exp -import kotlin.math.pow -import kotlin.math.sqrt - -abstract class ContinuousSamplerDistribution : Distribution { - - private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingRealChain() { - private val sampler = buildCMSampler(generator) - - override fun nextDouble(): Double = sampler.sample() - - override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) - } - - protected abstract fun buildCMSampler(generator: RandomGenerator): ContinuousSampler - - override fun sample(generator: RandomGenerator): BlockingRealChain = ContinuousSamplerChain(generator) -} - -abstract class DiscreteSamplerDistribution : Distribution { - - private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingIntChain() { - private val sampler = buildSampler(generator) - - override fun nextInt(): Int = sampler.sample() - - override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) - } - - protected abstract fun buildSampler(generator: RandomGenerator): DiscreteSampler - - override fun sample(generator: RandomGenerator): BlockingIntChain = ContinuousSamplerChain(generator) -} - -enum class NormalSamplerMethod { - BoxMuller, - Marsaglia, - Ziggurat -} - -private fun normalSampler(method: NormalSamplerMethod, provider: UniformRandomProvider): NormalizedGaussianSampler = - when (method) { - NormalSamplerMethod.BoxMuller -> BoxMullerNormalizedGaussianSampler(provider) - NormalSamplerMethod.Marsaglia -> MarsagliaNormalizedGaussianSampler(provider) - NormalSamplerMethod.Ziggurat -> ZigguratNormalizedGaussianSampler(provider) - } - -fun Distribution.Companion.normal( - method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat -): Distribution = object : ContinuousSamplerDistribution() { - override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler { - val provider: UniformRandomProvider = generator.asUniformRandomProvider() - return normalSampler(method, provider) - } - - override fun probability(arg: Double): Double { - return exp(-arg.pow(2) / 2) / sqrt(PI * 2) - } -} - -fun Distribution.Companion.normal( - mean: Double, - sigma: Double, - method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat -): ContinuousSamplerDistribution = object : ContinuousSamplerDistribution() { - private val sigma2 = sigma.pow(2) - private val norm = sigma * sqrt(PI * 2) - - override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler { - val provider: UniformRandomProvider = generator.asUniformRandomProvider() - val normalizedSampler = normalSampler(method, provider) - return GaussianSampler(normalizedSampler, mean, sigma) - } - - override fun probability(arg: Double): Double { - return exp(-(arg - mean).pow(2) / 2 / sigma2) / norm - } -} - -fun Distribution.Companion.poisson( - lambda: Double -): DiscreteSamplerDistribution = object : DiscreteSamplerDistribution() { - - override fun buildSampler(generator: RandomGenerator): DiscreteSampler { - return PoissonSampler.of(generator.asUniformRandomProvider(), lambda) - } - - private val computedProb: HashMap = hashMapOf(0 to exp(-lambda)) - - override fun probability(arg: Int): Double { - require(arg >= 0) { "The argument must be >= 0" } - return if (arg > 40) { - exp(-(arg - lambda).pow(2) / 2 / lambda) / sqrt(2 * PI * lambda) - } else { - computedProb.getOrPut(arg) { - probability(arg - 1) * lambda / arg - } - } - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 57173250b..f73a80994 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -35,6 +35,7 @@ include( ":kmath-functions", // ":kmath-io", ":kmath-coroutines", + "kmath-commons-rng-part", ":kmath-histograms", ":kmath-commons", ":kmath-viktor", From bc59f8b2875e5d3fd0e93b77d45f923a79db844f Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 8 Jun 2020 15:13:54 +0700 Subject: [PATCH 002/393] Merger kmath-prob and kmath-commons-rng-part --- kmath-commons-rng-part/build.gradle.kts | 2 - .../rng/sampling/SharedStateSampler.kt | 7 --- .../distribution/ContinuousSampler.kt | 5 -- .../sampling/distribution/DiscreteSampler.kt | 5 -- .../distribution/NormalizedGaussianSampler.kt | 3 -- .../SharedStateContinuousSampler.kt | 7 --- kmath-prob/build.gradle.kts | 15 ++---- .../commons/rng/UniformRandomProvider.kt | 2 +- .../rng/sampling/SharedStateSampler.kt | 7 +++ .../AhrensDieterExponentialSampler.kt | 14 +++-- .../BoxMullerNormalizedGaussianSampler.kt | 4 +- .../distribution/ContinuousSampler.kt | 5 ++ .../sampling/distribution/DiscreteSampler.kt | 5 ++ .../sampling/distribution/GaussianSampler.kt | 20 +++++-- .../sampling/distribution/InternalGamma.kt | 2 +- .../sampling/distribution/InternalUtils.kt | 33 ++++++++---- .../KempSmallMeanPoissonSampler.kt | 10 ++-- .../distribution/LargenMeanPoissonSampler.kt | 38 +++++++++---- .../MarsagliaNormalizedGaussianSampler.kt | 4 +- .../distribution/NormalizedGaussianSampler.kt | 4 ++ .../sampling/distribution/PoissonSampler.kt | 18 +++++-- .../rng/sampling/distribution/SamplerBase.kt | 4 +- .../SharedStateContinuousSampler.kt | 7 +++ .../SharedStateDiscreteSampler.kt | 4 +- .../distribution/SmallMeanPoissonSampler.kt | 10 ++-- .../ZigguratNormalizedGaussianSampler.kt | 22 +++++--- .../scientifik/kmath/prob/Distributions.kt | 53 ------------------- .../kmath/prob/RandomSourceGenerator.kt | 5 +- .../{Distributions.kt => DistributionsJVM.kt} | 14 +++-- .../kmath/prob/RandomSourceGenerator.kt | 2 +- settings.gradle.kts | 2 +- 31 files changed, 175 insertions(+), 158 deletions(-) delete mode 100644 kmath-commons-rng-part/build.gradle.kts delete mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/SharedStateSampler.kt delete mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ContinuousSampler.kt delete mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/DiscreteSampler.kt delete mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt delete mode 100644 kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/UniformRandomProvider.kt (90%) create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/SharedStateSampler.kt rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt (88%) rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt (92%) create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ContinuousSampler.kt create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/DiscreteSampler.kt rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/GaussianSampler.kt (69%) rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/InternalGamma.kt (95%) rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/InternalUtils.kt (72%) rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt (88%) rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt (88%) rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt (94%) create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/PoissonSampler.kt (64%) rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/SamplerBase.kt (78%) create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt (52%) rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt (83%) rename {kmath-commons-rng-part/src/commonMain/kotlin/scientifik => kmath-prob/src/commonMain/kotlin/scientifik/kmath}/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt (86%) delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distributions.kt rename kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/{Distributions.kt => DistributionsJVM.kt} (82%) diff --git a/kmath-commons-rng-part/build.gradle.kts b/kmath-commons-rng-part/build.gradle.kts deleted file mode 100644 index 9d3cd0e7d..000000000 --- a/kmath-commons-rng-part/build.gradle.kts +++ /dev/null @@ -1,2 +0,0 @@ -plugins { id("scientifik.mpp") } -kotlin.sourceSets { commonMain.get().dependencies { api(project(":kmath-coroutines")) } } diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/SharedStateSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/SharedStateSampler.kt deleted file mode 100644 index d32a646c2..000000000 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/SharedStateSampler.kt +++ /dev/null @@ -1,7 +0,0 @@ -package scientifik.commons.rng.sampling - -import scientifik.commons.rng.UniformRandomProvider - -interface SharedStateSampler { - fun withUniformRandomProvider(rng: UniformRandomProvider): R -} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ContinuousSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ContinuousSampler.kt deleted file mode 100644 index 4841672a2..000000000 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ContinuousSampler.kt +++ /dev/null @@ -1,5 +0,0 @@ -package scientifik.commons.rng.sampling.distribution - -interface ContinuousSampler { - fun sample(): Double -} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/DiscreteSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/DiscreteSampler.kt deleted file mode 100644 index 8e8bccd18..000000000 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/DiscreteSampler.kt +++ /dev/null @@ -1,5 +0,0 @@ -package scientifik.commons.rng.sampling.distribution - -interface DiscreteSampler { - fun sample(): Int -} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt deleted file mode 100644 index feff4d954..000000000 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt +++ /dev/null @@ -1,3 +0,0 @@ -package scientifik.commons.rng.sampling.distribution - -interface NormalizedGaussianSampler : ContinuousSampler diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt b/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt deleted file mode 100644 index ddac4b7a7..000000000 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt +++ /dev/null @@ -1,7 +0,0 @@ -package scientifik.commons.rng.sampling.distribution - -import scientifik.commons.rng.sampling.SharedStateSampler - -interface SharedStateContinuousSampler : ContinuousSampler, - SharedStateSampler { -} diff --git a/kmath-prob/build.gradle.kts b/kmath-prob/build.gradle.kts index 4ec254e82..4c1d7f949 100644 --- a/kmath-prob/build.gradle.kts +++ b/kmath-prob/build.gradle.kts @@ -3,17 +3,10 @@ plugins { } kotlin.sourceSets { - commonMain { - dependencies { - api(project(":kmath-coroutines")) - api(project(":kmath-commons-rng-part")) - } - } + commonMain.get().dependencies { api(project(":kmath-coroutines")) } - jvmMain { - dependencies { - api("org.apache.commons:commons-rng-sampling:1.3") - api("org.apache.commons:commons-rng-simple:1.3") - } + jvmMain.get().dependencies { + api("org.apache.commons:commons-rng-sampling:1.3") + api("org.apache.commons:commons-rng-simple:1.3") } } \ No newline at end of file diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/UniformRandomProvider.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/UniformRandomProvider.kt similarity index 90% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/UniformRandomProvider.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/UniformRandomProvider.kt index 2fbf7a0a2..bd6d30124 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/UniformRandomProvider.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/UniformRandomProvider.kt @@ -1,4 +1,4 @@ -package scientifik.commons.rng +package scientifik.kmath.commons.rng interface UniformRandomProvider { fun nextBytes(bytes: ByteArray) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/SharedStateSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/SharedStateSampler.kt new file mode 100644 index 000000000..30ccefb54 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/SharedStateSampler.kt @@ -0,0 +1,7 @@ +package scientifik.kmath.commons.rng.sampling + +import scientifik.kmath.commons.rng.UniformRandomProvider + +interface SharedStateSampler { + fun withUniformRandomProvider(rng: UniformRandomProvider): R +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt similarity index 88% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt index 7aa061951..714cf2164 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt @@ -1,6 +1,6 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution -import scientifik.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.UniformRandomProvider import kotlin.math.ln import kotlin.math.pow @@ -76,7 +76,11 @@ class AhrensDieterExponentialSampler : SamplerBase, fun of( rng: UniformRandomProvider, mean: Double - ): SharedStateContinuousSampler = AhrensDieterExponentialSampler(rng, mean) + ): SharedStateContinuousSampler = + AhrensDieterExponentialSampler( + rng, + mean + ) init { /** @@ -87,7 +91,9 @@ class AhrensDieterExponentialSampler : SamplerBase, var qi = 0.0 EXPONENTIAL_SA_QI.indices.forEach { i -> - qi += ln2.pow(i + 1.0) / InternalUtils.factorial(i + 1) + qi += ln2.pow(i + 1.0) / InternalUtils.factorial( + i + 1 + ) EXPONENTIAL_SA_QI[i] = qi } } diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt similarity index 92% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt index 91b3314b5..0e927bb32 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt @@ -1,6 +1,6 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution -import scientifik.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.UniformRandomProvider import kotlin.math.* class BoxMullerNormalizedGaussianSampler( diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ContinuousSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ContinuousSampler.kt new file mode 100644 index 000000000..aea81cf92 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ContinuousSampler.kt @@ -0,0 +1,5 @@ +package scientifik.kmath.commons.rng.sampling.distribution + +interface ContinuousSampler { + fun sample(): Double +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/DiscreteSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/DiscreteSampler.kt new file mode 100644 index 000000000..4de780424 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/DiscreteSampler.kt @@ -0,0 +1,5 @@ +package scientifik.kmath.commons.rng.sampling.distribution + +interface DiscreteSampler { + fun sample(): Int +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/GaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/GaussianSampler.kt similarity index 69% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/GaussianSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/GaussianSampler.kt index 424ea90fe..0b54a0ad1 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/GaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/GaussianSampler.kt @@ -1,8 +1,9 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution -import scientifik.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.UniformRandomProvider -class GaussianSampler : SharedStateContinuousSampler { +class GaussianSampler : + SharedStateContinuousSampler { private val mean: Double private val standardDeviation: Double private val normalized: NormalizedGaussianSampler @@ -24,7 +25,11 @@ class GaussianSampler : SharedStateContinuousSampler { ) { mean = source.mean standardDeviation = source.standardDeviation - normalized = InternalUtils.newNormalizedGaussianSampler(source.normalized, rng) + normalized = + InternalUtils.newNormalizedGaussianSampler( + source.normalized, + rng + ) } override fun sample(): Double = standardDeviation * normalized.sample() + mean @@ -40,6 +45,11 @@ class GaussianSampler : SharedStateContinuousSampler { normalized: NormalizedGaussianSampler, mean: Double, standardDeviation: Double - ): SharedStateContinuousSampler = GaussianSampler(normalized, mean, standardDeviation) + ): SharedStateContinuousSampler = + GaussianSampler( + normalized, + mean, + standardDeviation + ) } } diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalGamma.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/InternalGamma.kt similarity index 95% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalGamma.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/InternalGamma.kt index a75ba1608..79426d7ae 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalGamma.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/InternalGamma.kt @@ -1,4 +1,4 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution import kotlin.math.PI import kotlin.math.ln diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalUtils.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/InternalUtils.kt similarity index 72% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalUtils.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/InternalUtils.kt index 8134252aa..0f563b956 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/InternalUtils.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/InternalUtils.kt @@ -1,7 +1,7 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution -import scientifik.commons.rng.UniformRandomProvider -import scientifik.commons.rng.sampling.SharedStateSampler +import scientifik.kmath.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.sampling.SharedStateSampler import kotlin.math.ln import kotlin.math.min @@ -63,30 +63,45 @@ internal object InternalUtils { if (cache != null && cache.size > BEGIN_LOG_FACTORIALS) { // Copy available values. endCopy = min(cache.size, numValues) - cache.copyInto(logFactorials, BEGIN_LOG_FACTORIALS, BEGIN_LOG_FACTORIALS, endCopy) + cache.copyInto(logFactorials, + BEGIN_LOG_FACTORIALS, + BEGIN_LOG_FACTORIALS, endCopy) } // All values to be computed else - endCopy = BEGIN_LOG_FACTORIALS + endCopy = + BEGIN_LOG_FACTORIALS // Compute remaining values. (endCopy until numValues).forEach { i -> - if (i < FACTORIALS.size) logFactorials[i] = ln(FACTORIALS[i].toDouble()) else logFactorials[i] = + if (i < FACTORIALS.size) logFactorials[i] = ln( + FACTORIALS[i].toDouble()) else logFactorials[i] = logFactorials[i - 1] + ln(i.toDouble()) } } - fun withCache(cacheSize: Int): FactorialLog = FactorialLog(cacheSize, logFactorials) + fun withCache(cacheSize: Int): FactorialLog = + FactorialLog( + cacheSize, + logFactorials + ) fun value(n: Int): Double { if (n < logFactorials.size) return logFactorials[n] - return if (n < FACTORIALS.size) ln(FACTORIALS[n].toDouble()) else InternalGamma.logGamma(n + 1.0) + return if (n < FACTORIALS.size) ln( + FACTORIALS[n].toDouble()) else InternalGamma.logGamma( + n + 1.0 + ) } companion object { - fun create(): FactorialLog = FactorialLog(0, null) + fun create(): FactorialLog = + FactorialLog( + 0, + null + ) } } } diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt similarity index 88% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt index 6501089b2..3072cf020 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt @@ -1,6 +1,6 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution -import scientifik.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.UniformRandomProvider import kotlin.math.exp class KempSmallMeanPoissonSampler private constructor( @@ -48,7 +48,11 @@ class KempSmallMeanPoissonSampler private constructor( val p0: Double = exp(-mean) // Probability must be positive. As mean increases then p(0) decreases. - if (p0 > 0) return KempSmallMeanPoissonSampler(rng, p0, mean) + if (p0 > 0) return KempSmallMeanPoissonSampler( + rng, + p0, + mean + ) throw IllegalArgumentException("No probability for mean: $mean") } } diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt similarity index 88% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt index ce1e1e3b0..ae7d3f079 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt @@ -1,9 +1,10 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution -import scientifik.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.UniformRandomProvider import kotlin.math.* -class LargeMeanPoissonSampler : SharedStateDiscreteSampler { +class LargeMeanPoissonSampler : + SharedStateDiscreteSampler { private val rng: UniformRandomProvider private val exponential: SharedStateContinuousSampler private val gaussian: SharedStateContinuousSampler @@ -27,8 +28,13 @@ class LargeMeanPoissonSampler : SharedStateDiscreteSampler { // The algorithm is not valid if Math.floor(mean) is not an integer. require(mean <= MAX_MEAN) { "mean $mean > $MAX_MEAN" } this.rng = rng - gaussian = ZigguratNormalizedGaussianSampler(rng) - exponential = AhrensDieterExponentialSampler.of(rng, 1.0) + gaussian = + ZigguratNormalizedGaussianSampler(rng) + exponential = + AhrensDieterExponentialSampler.of( + rng, + 1.0 + ) // Plain constructor uses the uncached function. factorialLog = NO_CACHE_FACTORIAL_LOG!! // Cache values used in the algorithm @@ -49,7 +55,10 @@ class LargeMeanPoissonSampler : SharedStateDiscreteSampler { val lambdaFractional = mean - lambda smallMeanPoissonSampler = if (lambdaFractional < Double.MIN_VALUE) NO_SMALL_MEAN_POISSON_SAMPLER else // Not used. - KempSmallMeanPoissonSampler.of(rng, lambdaFractional) + KempSmallMeanPoissonSampler.of( + rng, + lambdaFractional + ) } internal constructor( @@ -59,8 +68,13 @@ class LargeMeanPoissonSampler : SharedStateDiscreteSampler { ) { require(!(lambdaFractional < 0 || lambdaFractional >= 1)) { "lambdaFractional must be in the range 0 (inclusive) to 1 (exclusive): $lambdaFractional" } this.rng = rng - gaussian = ZigguratNormalizedGaussianSampler(rng) - exponential = AhrensDieterExponentialSampler.of(rng, 1.0) + gaussian = + ZigguratNormalizedGaussianSampler(rng) + exponential = + AhrensDieterExponentialSampler.of( + rng, + 1.0 + ) // Plain constructor uses the uncached function. factorialLog = NO_CACHE_FACTORIAL_LOG!! // Use the state to initialise the algorithm @@ -79,7 +93,10 @@ class LargeMeanPoissonSampler : SharedStateDiscreteSampler { if (lambdaFractional < Double.MIN_VALUE) NO_SMALL_MEAN_POISSON_SAMPLER else // Not used. - KempSmallMeanPoissonSampler.of(rng, lambdaFractional) + KempSmallMeanPoissonSampler.of( + rng, + lambdaFractional + ) } /** @@ -222,7 +239,8 @@ class LargeMeanPoissonSampler : SharedStateDiscreteSampler { fun of( rng: UniformRandomProvider, mean: Double - ): SharedStateDiscreteSampler = LargeMeanPoissonSampler(rng, mean) + ): SharedStateDiscreteSampler = + LargeMeanPoissonSampler(rng, mean) init { // Create without a cache. diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt similarity index 94% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt index 26ee9ece9..ee346718e 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt @@ -1,6 +1,6 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution -import scientifik.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.UniformRandomProvider import kotlin.math.ln import kotlin.math.sqrt diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt new file mode 100644 index 000000000..c47b9b4e9 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt @@ -0,0 +1,4 @@ +package scientifik.kmath.commons.rng.sampling.distribution + +interface NormalizedGaussianSampler : + ContinuousSampler diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/PoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/PoissonSampler.kt similarity index 64% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/PoissonSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/PoissonSampler.kt index 4a7f56f60..a440c3a7d 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/PoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/PoissonSampler.kt @@ -1,11 +1,12 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution -import scientifik.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.UniformRandomProvider class PoissonSampler( rng: UniformRandomProvider, mean: Double -) : SamplerBase(null), SharedStateDiscreteSampler { +) : SamplerBase(null), + SharedStateDiscreteSampler { private val poissonSamplerDelegate: SharedStateDiscreteSampler override fun sample(): Int = poissonSamplerDelegate.sample() @@ -22,11 +23,18 @@ class PoissonSampler( rng: UniformRandomProvider, mean: Double ): SharedStateDiscreteSampler =// Each sampler should check the input arguments. - if (mean < PIVOT) SmallMeanPoissonSampler.of(rng, mean) else LargeMeanPoissonSampler.of(rng, mean) + if (mean < PIVOT) SmallMeanPoissonSampler.of( + rng, + mean + ) else LargeMeanPoissonSampler.of( + rng, + mean + ) } init { // Delegate all work to specialised samplers. - poissonSamplerDelegate = of(rng, mean) + poissonSamplerDelegate = + of(rng, mean) } } \ No newline at end of file diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SamplerBase.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SamplerBase.kt similarity index 78% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SamplerBase.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SamplerBase.kt index 38df9eb4e..4170e9db3 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SamplerBase.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SamplerBase.kt @@ -1,6 +1,6 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution -import scientifik.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.UniformRandomProvider @Deprecated("Since version 1.1. Class intended for internal use only.") open class SamplerBase protected constructor(private val rng: UniformRandomProvider?) { diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt new file mode 100644 index 000000000..c833ce8de --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt @@ -0,0 +1,7 @@ +package scientifik.kmath.commons.rng.sampling.distribution + +import scientifik.kmath.commons.rng.sampling.SharedStateSampler + +interface SharedStateContinuousSampler : ContinuousSampler, + SharedStateSampler { +} diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt similarity index 52% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt index 2d8adada6..7b17e4670 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt @@ -1,6 +1,6 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution -import scientifik.commons.rng.sampling.SharedStateSampler +import scientifik.kmath.commons.rng.sampling.SharedStateSampler interface SharedStateDiscreteSampler : DiscreteSampler, SharedStateSampler { // Composite interface diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt similarity index 83% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt index a3188620f..a35dd277c 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt @@ -1,10 +1,11 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution -import scientifik.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.UniformRandomProvider import kotlin.math.ceil import kotlin.math.exp -class SmallMeanPoissonSampler : SharedStateDiscreteSampler { +class SmallMeanPoissonSampler : + SharedStateDiscreteSampler { private val p0: Double private val limit: Int private val rng: UniformRandomProvider @@ -53,6 +54,7 @@ class SmallMeanPoissonSampler : SharedStateDiscreteSampler { fun of( rng: UniformRandomProvider, mean: Double - ): SharedStateDiscreteSampler = SmallMeanPoissonSampler(rng, mean) + ): SharedStateDiscreteSampler = + SmallMeanPoissonSampler(rng, mean) } } \ No newline at end of file diff --git a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt similarity index 86% rename from kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt index a916121db..26e089599 100644 --- a/kmath-commons-rng-part/src/commonMain/kotlin/scientifik/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt @@ -1,6 +1,6 @@ -package scientifik.commons.rng.sampling.distribution +package scientifik.kmath.commons.rng.sampling.distribution -import scientifik.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.UniformRandomProvider import kotlin.math.* class ZigguratNormalizedGaussianSampler(private val rng: UniformRandomProvider) : @@ -26,9 +26,13 @@ class ZigguratNormalizedGaussianSampler(private val rng: UniformRandomProvider) init { // Filling the tables. - var d = R + var d = + R var t = d - var fd = gauss(d) + var fd = + gauss( + d + ) val q = V / fd K[0] = (d / q * MAX).toLong() K[1] = 0 @@ -39,7 +43,10 @@ class ZigguratNormalizedGaussianSampler(private val rng: UniformRandomProvider) (LAST - 1 downTo 1).forEach { i -> d = sqrt(-2 * ln(V / d + fd)) - fd = gauss(d) + fd = + gauss( + d + ) K[i + 1] = (d / t * MAX).toLong() t = d F[i] = fd @@ -80,7 +87,10 @@ class ZigguratNormalizedGaussianSampler(private val rng: UniformRandomProvider) // else // Try again. // This branch is called about 0.012362 times per sample. - if (F[iz] + rng.nextDouble() * (F[iz - 1] - F[iz]) < gauss(x)) x else sample() + if (F[iz] + rng.nextDouble() * (F[iz - 1] - F[iz]) < gauss( + x + ) + ) x else sample() } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distributions.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distributions.kt deleted file mode 100644 index fd8cc4116..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distributions.kt +++ /dev/null @@ -1,53 +0,0 @@ -package scientifik.kmath.prob - -import scientifik.commons.rng.UniformRandomProvider -import scientifik.commons.rng.sampling.distribution.* -import scientifik.kmath.chains.BlockingIntChain -import scientifik.kmath.chains.BlockingRealChain -import scientifik.kmath.chains.Chain - -abstract class ContinuousSamplerDistribution : Distribution { - - private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingRealChain() { - private val sampler = buildCMSampler(generator) - - override fun nextDouble(): Double = sampler.sample() - - override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) - } - - protected abstract fun buildCMSampler(generator: RandomGenerator): ContinuousSampler - - override fun sample(generator: RandomGenerator): BlockingRealChain = ContinuousSamplerChain(generator) -} - -abstract class DiscreteSamplerDistribution : Distribution { - - private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingIntChain() { - private val sampler = buildSampler(generator) - - override fun nextInt(): Int = sampler.sample() - - override fun fork(): Chain = ContinuousSamplerChain(generator.fork()) - } - - protected abstract fun buildSampler(generator: RandomGenerator): DiscreteSampler - - override fun sample(generator: RandomGenerator): BlockingIntChain = ContinuousSamplerChain(generator) -} - -enum class NormalSamplerMethod { - BoxMuller, - Marsaglia, - Ziggurat -} - -fun normalSampler(method: NormalSamplerMethod, provider: UniformRandomProvider): NormalizedGaussianSampler = - when (method) { - NormalSamplerMethod.BoxMuller -> BoxMullerNormalizedGaussianSampler( - provider - ) - NormalSamplerMethod.Marsaglia -> MarsagliaNormalizedGaussianSampler(provider) - NormalSamplerMethod.Ziggurat -> ZigguratNormalizedGaussianSampler(provider) - } - diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt index 7be8276f3..b4056cabc 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt @@ -1,9 +1,10 @@ package scientifik.kmath.prob -import scientifik.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.UniformRandomProvider -inline class RandomGeneratorProvider(val generator: RandomGenerator) : UniformRandomProvider { +inline class RandomGeneratorProvider(val generator: RandomGenerator) : + UniformRandomProvider { override fun nextBoolean(): Boolean = generator.nextBoolean() override fun nextFloat(): Float = generator.nextDouble().toFloat() diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/Distributions.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/DistributionsJVM.kt similarity index 82% rename from kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/Distributions.kt rename to kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/DistributionsJVM.kt index aaeeb1b26..649cae961 100644 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/Distributions.kt +++ b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/DistributionsJVM.kt @@ -1,9 +1,9 @@ package scientifik.kmath.prob -import scientifik.commons.rng.sampling.distribution.ContinuousSampler -import scientifik.commons.rng.sampling.distribution.DiscreteSampler -import scientifik.commons.rng.sampling.distribution.GaussianSampler -import scientifik.commons.rng.sampling.distribution.PoissonSampler +import scientifik.kmath.commons.rng.sampling.distribution.ContinuousSampler +import scientifik.kmath.commons.rng.sampling.distribution.DiscreteSampler +import scientifik.kmath.commons.rng.sampling.distribution.GaussianSampler +import scientifik.kmath.commons.rng.sampling.distribution.PoissonSampler import kotlin.math.PI import kotlin.math.exp import kotlin.math.pow @@ -33,7 +33,11 @@ fun Distribution.Companion.normal( override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler { val provider = generator.asUniformRandomProvider() val normalizedSampler = normalSampler(method, provider) - return GaussianSampler(normalizedSampler, mean, sigma) + return GaussianSampler( + normalizedSampler, + mean, + sigma + ) } override fun probability(arg: Double): Double { diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt index 8c4b59abb..4c8d630ae 100644 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt +++ b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt @@ -1,7 +1,7 @@ package scientifik.kmath.prob import org.apache.commons.rng.simple.RandomSource -import scientifik.commons.rng.UniformRandomProvider +import scientifik.kmath.commons.rng.UniformRandomProvider class RandomSourceGenerator(val source: RandomSource, seed: Long?) : RandomGenerator { diff --git a/settings.gradle.kts b/settings.gradle.kts index f73a80994..5e584dc58 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -29,13 +29,13 @@ pluginManagement { } rootProject.name = "kmath" + include( ":kmath-memory", ":kmath-core", ":kmath-functions", // ":kmath-io", ":kmath-coroutines", - "kmath-commons-rng-part", ":kmath-histograms", ":kmath-commons", ":kmath-viktor", From 28062cb09637801b7628a6b31c1a02cb1674531d Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 8 Jun 2020 17:16:57 +0700 Subject: [PATCH 003/393] Minimal refactor of existing random API, move samplers implementations to samplers package, implement Sampler by all the Samplers --- .../kotlin/scientifik/kmath/chains/Chain.kt | 65 ++--- .../commons/rng/UniformRandomProvider.kt | 19 -- .../rng/sampling/SharedStateSampler.kt | 7 - .../AhrensDieterExponentialSampler.kt | 101 ------- .../BoxMullerNormalizedGaussianSampler.kt | 50 ---- .../distribution/ContinuousSampler.kt | 5 - .../sampling/distribution/DiscreteSampler.kt | 5 - .../sampling/distribution/GaussianSampler.kt | 55 ---- .../distribution/LargenMeanPoissonSampler.kt | 251 ------------------ .../distribution/NormalizedGaussianSampler.kt | 4 - .../sampling/distribution/PoissonSampler.kt | 40 --- .../rng/sampling/distribution/SamplerBase.kt | 12 - .../SharedStateContinuousSampler.kt | 7 - .../SharedStateDiscreteSampler.kt | 7 - .../distribution/SmallMeanPoissonSampler.kt | 60 ----- .../scientifik/kmath/prob/Distribution.kt | 3 + .../kmath/prob/FactorizedDistribution.kt | 1 - .../scientifik/kmath/prob/RandomGenerator.kt | 10 +- .../AhrensDieterExponentialSampler.kt | 68 +++++ .../BoxMullerNormalizedGaussianSampler.kt | 37 +++ .../kmath/prob/samplers/GaussianSampler.kt | 34 +++ .../samplers}/InternalGamma.kt | 4 +- .../samplers}/InternalUtils.kt | 50 +--- .../samplers}/KempSmallMeanPoissonSampler.kt | 35 +-- .../prob/samplers/LargeMeanPoissonSampler.kt | 132 +++++++++ .../MarsagliaNormalizedGaussianSampler.kt | 42 ++- .../samplers/NormalizedGaussianSampler.kt | 5 + .../kmath/prob/samplers/PoissonSampler.kt | 29 ++ .../prob/samplers/SmallMeanPoissonSampler.kt | 43 +++ .../ZigguratNormalizedGaussianSampler.kt | 118 ++++---- .../scientifik/kmath/prob/DistributionsJVM.kt | 66 ----- .../kmath/prob/RandomSourceGenerator.kt | 23 +- 32 files changed, 485 insertions(+), 903 deletions(-) delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/UniformRandomProvider.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/SharedStateSampler.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ContinuousSampler.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/DiscreteSampler.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/GaussianSampler.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/PoissonSampler.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SamplerBase.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt rename kmath-prob/src/commonMain/kotlin/scientifik/kmath/{commons/rng/sampling/distribution => prob/samplers}/InternalGamma.kt (93%) rename kmath-prob/src/commonMain/kotlin/scientifik/kmath/{commons/rng/sampling/distribution => prob/samplers}/InternalUtils.kt (55%) rename kmath-prob/src/commonMain/kotlin/scientifik/kmath/{commons/rng/sampling/distribution => prob/samplers}/KempSmallMeanPoissonSampler.kt (66%) create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt rename kmath-prob/src/commonMain/kotlin/scientifik/kmath/{commons/rng/sampling/distribution => prob/samplers}/MarsagliaNormalizedGaussianSampler.kt (53%) create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/NormalizedGaussianSampler.kt create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/PoissonSampler.kt create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt rename kmath-prob/src/commonMain/kotlin/scientifik/kmath/{commons/rng/sampling/distribution => prob/samplers}/ZigguratNormalizedGaussianSampler.kt (58%) delete mode 100644 kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/DistributionsJVM.kt diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt index 5635499e5..6457c74fd 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/Chain.kt @@ -19,6 +19,7 @@ package scientifik.kmath.chains import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock @@ -27,7 +28,7 @@ import kotlinx.coroutines.sync.withLock * A not-necessary-Markov chain of some type * @param R - the chain element type */ -interface Chain: Flow { +interface Chain : Flow { /** * Generate next value, changing state if needed */ @@ -39,13 +40,11 @@ interface Chain: Flow { fun fork(): Chain @OptIn(InternalCoroutinesApi::class) - override suspend fun collect(collector: FlowCollector) { - kotlinx.coroutines.flow.flow { - while (true){ - emit(next()) - } - }.collect(collector) - } + override suspend fun collect(collector: FlowCollector): Unit = flow { + while (true) + emit(next()) + + }.collect(collector) companion object } @@ -66,24 +65,18 @@ class SimpleChain(private val gen: suspend () -> R) : Chain { * A stateless Markov chain */ class MarkovChain(private val seed: suspend () -> R, private val gen: suspend (R) -> R) : Chain { - - private val mutex = Mutex() - + private val mutex: Mutex = Mutex() private var value: R? = null fun value() = value - override suspend fun next(): R { - mutex.withLock { - val newValue = gen(value ?: seed()) - value = newValue - return newValue - } + override suspend fun next(): R = mutex.withLock { + val newValue = gen(value ?: seed()) + value = newValue + return newValue } - override fun fork(): Chain { - return MarkovChain(seed = { value ?: seed() }, gen = gen) - } + override fun fork(): Chain = MarkovChain(seed = { value ?: seed() }, gen = gen) } /** @@ -97,24 +90,18 @@ class StatefulChain( private val forkState: ((S) -> S), private val gen: suspend S.(R) -> R ) : Chain { - private val mutex = Mutex() - private var value: R? = null fun value() = value - override suspend fun next(): R { - mutex.withLock { - val newValue = state.gen(value ?: state.seed()) - value = newValue - return newValue - } + override suspend fun next(): R = mutex.withLock { + val newValue = state.gen(value ?: state.seed()) + value = newValue + return newValue } - override fun fork(): Chain { - return StatefulChain(forkState(state), seed, forkState, gen) - } + override fun fork(): Chain = StatefulChain(forkState(state), seed, forkState, gen) } /** @@ -123,9 +110,7 @@ class StatefulChain( class ConstantChain(val value: T) : Chain { override suspend fun next(): T = value - override fun fork(): Chain { - return this - } + override fun fork(): Chain = this } /** @@ -143,9 +128,8 @@ fun Chain.map(func: suspend (T) -> R): Chain = object : Chain { fun Chain.filter(block: (T) -> Boolean): Chain = object : Chain { override suspend fun next(): T { var next: T - do { - next = this@filter.next() - } while (!block(next)) + do next = this@filter.next() + while (!block(next)) return next } @@ -163,7 +147,9 @@ fun Chain.collect(mapper: suspend (Chain) -> R): Chain = object fun Chain.collectWithState(state: S, stateFork: (S) -> S, mapper: suspend S.(Chain) -> R): Chain = object : Chain { override suspend fun next(): R = state.mapper(this@collectWithState) - override fun fork(): Chain = this@collectWithState.fork().collectWithState(stateFork(state), stateFork, mapper) + + override fun fork(): Chain = + this@collectWithState.fork().collectWithState(stateFork(state), stateFork, mapper) } /** @@ -171,6 +157,5 @@ fun Chain.collectWithState(state: S, stateFork: (S) -> S, mapper: s */ fun Chain.zip(other: Chain, block: suspend (T, U) -> R): Chain = object : Chain { override suspend fun next(): R = block(this@zip.next(), other.next()) - override fun fork(): Chain = this@zip.fork().zip(other.fork(), block) -} \ No newline at end of file +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/UniformRandomProvider.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/UniformRandomProvider.kt deleted file mode 100644 index bd6d30124..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/UniformRandomProvider.kt +++ /dev/null @@ -1,19 +0,0 @@ -package scientifik.kmath.commons.rng - -interface UniformRandomProvider { - fun nextBytes(bytes: ByteArray) - - fun nextBytes( - bytes: ByteArray, - start: Int, - len: Int - ) - - fun nextInt(): Int - fun nextInt(n: Int): Int - fun nextLong(): Long - fun nextLong(n: Long): Long - fun nextBoolean(): Boolean - fun nextFloat(): Float - fun nextDouble(): Double -} \ No newline at end of file diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/SharedStateSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/SharedStateSampler.kt deleted file mode 100644 index 30ccefb54..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/SharedStateSampler.kt +++ /dev/null @@ -1,7 +0,0 @@ -package scientifik.kmath.commons.rng.sampling - -import scientifik.kmath.commons.rng.UniformRandomProvider - -interface SharedStateSampler { - fun withUniformRandomProvider(rng: UniformRandomProvider): R -} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt deleted file mode 100644 index 714cf2164..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.kt +++ /dev/null @@ -1,101 +0,0 @@ -package scientifik.kmath.commons.rng.sampling.distribution - -import scientifik.kmath.commons.rng.UniformRandomProvider -import kotlin.math.ln -import kotlin.math.pow - -class AhrensDieterExponentialSampler : SamplerBase, - SharedStateContinuousSampler { - private val mean: Double - private val rng: UniformRandomProvider - - constructor( - rng: UniformRandomProvider, - mean: Double - ) : super(null) { - require(mean > 0) { "mean is not strictly positive: $mean" } - this.rng = rng - this.mean = mean - } - - private constructor( - rng: UniformRandomProvider, - source: AhrensDieterExponentialSampler - ) : super(null) { - this.rng = rng - mean = source.mean - } - - override fun sample(): Double { - // Step 1: - var a = 0.0 - var u: Double = rng.nextDouble() - - // Step 2 and 3: - while (u < 0.5) { - a += EXPONENTIAL_SA_QI.get( - 0 - ) - u *= 2.0 - } - - // Step 4 (now u >= 0.5): - u += u - 1 - - // Step 5: - if (u <= EXPONENTIAL_SA_QI.get( - 0 - ) - ) { - return mean * (a + u) - } - - // Step 6: - var i = 0 // Should be 1, be we iterate before it in while using 0. - var u2: Double = rng.nextDouble() - var umin = u2 - - // Step 7 and 8: - do { - ++i - u2 = rng.nextDouble() - if (u2 < umin) umin = u2 - // Step 8: - } while (u > EXPONENTIAL_SA_QI[i]) // Ensured to exit since EXPONENTIAL_SA_QI[MAX] = 1. - return mean * (a + umin * EXPONENTIAL_SA_QI[0]) - } - - override fun toString(): String = "Ahrens-Dieter Exponential deviate [$rng]" - - override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateContinuousSampler = - AhrensDieterExponentialSampler(rng, this) - - companion object { - private val EXPONENTIAL_SA_QI = DoubleArray(16) - - fun of( - rng: UniformRandomProvider, - mean: Double - ): SharedStateContinuousSampler = - AhrensDieterExponentialSampler( - rng, - mean - ) - - init { - /** - * Filling EXPONENTIAL_SA_QI table. - * Note that we don't want qi = 0 in the table. - */ - val ln2 = ln(2.0) - var qi = 0.0 - - EXPONENTIAL_SA_QI.indices.forEach { i -> - qi += ln2.pow(i + 1.0) / InternalUtils.factorial( - i + 1 - ) - EXPONENTIAL_SA_QI[i] = qi - } - } - } -} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt deleted file mode 100644 index 0e927bb32..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.kt +++ /dev/null @@ -1,50 +0,0 @@ -package scientifik.kmath.commons.rng.sampling.distribution - -import scientifik.kmath.commons.rng.UniformRandomProvider -import kotlin.math.* - -class BoxMullerNormalizedGaussianSampler( - private val rng: UniformRandomProvider -) : - NormalizedGaussianSampler, - SharedStateContinuousSampler { - private var nextGaussian: Double = Double.NaN - - override fun sample(): Double { - val random: Double - - if (nextGaussian.isNaN()) { - // Generate a pair of Gaussian numbers. - val x = rng.nextDouble() - val y = rng.nextDouble() - val alpha = 2 * PI * x - val r = sqrt(-2 * ln(y)) - - // Return the first element of the generated pair. - random = r * cos(alpha) - - // Keep second element of the pair for next invocation. - nextGaussian = r * sin(alpha) - } else { - // Use the second element of the pair (generated at the - // previous invocation). - random = nextGaussian - - // Both elements of the pair have been used. - nextGaussian = Double.NaN - } - - return random - } - - override fun toString(): String = "Box-Muller normalized Gaussian deviate [$rng]" - - override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateContinuousSampler = - BoxMullerNormalizedGaussianSampler(rng) - - companion object { - @Suppress("UNCHECKED_CAST") - fun of(rng: UniformRandomProvider): S where S : NormalizedGaussianSampler?, S : SharedStateContinuousSampler? = - BoxMullerNormalizedGaussianSampler(rng) as S - } -} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ContinuousSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ContinuousSampler.kt deleted file mode 100644 index aea81cf92..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ContinuousSampler.kt +++ /dev/null @@ -1,5 +0,0 @@ -package scientifik.kmath.commons.rng.sampling.distribution - -interface ContinuousSampler { - fun sample(): Double -} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/DiscreteSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/DiscreteSampler.kt deleted file mode 100644 index 4de780424..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/DiscreteSampler.kt +++ /dev/null @@ -1,5 +0,0 @@ -package scientifik.kmath.commons.rng.sampling.distribution - -interface DiscreteSampler { - fun sample(): Int -} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/GaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/GaussianSampler.kt deleted file mode 100644 index 0b54a0ad1..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/GaussianSampler.kt +++ /dev/null @@ -1,55 +0,0 @@ -package scientifik.kmath.commons.rng.sampling.distribution - -import scientifik.kmath.commons.rng.UniformRandomProvider - -class GaussianSampler : - SharedStateContinuousSampler { - private val mean: Double - private val standardDeviation: Double - private val normalized: NormalizedGaussianSampler - - constructor( - normalized: NormalizedGaussianSampler, - mean: Double, - standardDeviation: Double - ) { - require(standardDeviation > 0) { "standard deviation is not strictly positive: $standardDeviation" } - this.normalized = normalized - this.mean = mean - this.standardDeviation = standardDeviation - } - - private constructor( - rng: UniformRandomProvider, - source: GaussianSampler - ) { - mean = source.mean - standardDeviation = source.standardDeviation - normalized = - InternalUtils.newNormalizedGaussianSampler( - source.normalized, - rng - ) - } - - override fun sample(): Double = standardDeviation * normalized.sample() + mean - - override fun toString(): String = "Gaussian deviate [$normalized]" - - override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateContinuousSampler { - return GaussianSampler(rng, this) - } - - companion object { - fun of( - normalized: NormalizedGaussianSampler, - mean: Double, - standardDeviation: Double - ): SharedStateContinuousSampler = - GaussianSampler( - normalized, - mean, - standardDeviation - ) - } -} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt deleted file mode 100644 index ae7d3f079..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/LargenMeanPoissonSampler.kt +++ /dev/null @@ -1,251 +0,0 @@ -package scientifik.kmath.commons.rng.sampling.distribution - -import scientifik.kmath.commons.rng.UniformRandomProvider -import kotlin.math.* - -class LargeMeanPoissonSampler : - SharedStateDiscreteSampler { - private val rng: UniformRandomProvider - private val exponential: SharedStateContinuousSampler - private val gaussian: SharedStateContinuousSampler - private val factorialLog: InternalUtils.FactorialLog - private val lambda: Double - private val logLambda: Double - private val logLambdaFactorial: Double - private val delta: Double - private val halfDelta: Double - private val twolpd: Double - private val p1: Double - private val p2: Double - private val c1: Double - private val smallMeanPoissonSampler: SharedStateDiscreteSampler - - constructor( - rng: UniformRandomProvider, - mean: Double - ) { - require(mean >= 1) { "mean is not >= 1: $mean" } - // The algorithm is not valid if Math.floor(mean) is not an integer. - require(mean <= MAX_MEAN) { "mean $mean > $MAX_MEAN" } - this.rng = rng - gaussian = - ZigguratNormalizedGaussianSampler(rng) - exponential = - AhrensDieterExponentialSampler.of( - rng, - 1.0 - ) - // Plain constructor uses the uncached function. - factorialLog = NO_CACHE_FACTORIAL_LOG!! - // Cache values used in the algorithm - lambda = floor(mean) - logLambda = ln(lambda) - logLambdaFactorial = getFactorialLog(lambda.toInt()) - delta = sqrt(lambda * ln(32 * lambda / PI + 1)) - halfDelta = delta / 2 - twolpd = 2 * lambda + delta - c1 = 1 / (8 * lambda) - val a1: Double = sqrt(PI * twolpd) * exp(c1) - val a2: Double = twolpd / delta * exp(-delta * (1 + delta) / twolpd) - val aSum = a1 + a2 + 1 - p1 = a1 / aSum - p2 = a2 / aSum - - // The algorithm requires a Poisson sample from the remaining lambda fraction. - val lambdaFractional = mean - lambda - smallMeanPoissonSampler = - if (lambdaFractional < Double.MIN_VALUE) NO_SMALL_MEAN_POISSON_SAMPLER else // Not used. - KempSmallMeanPoissonSampler.of( - rng, - lambdaFractional - ) - } - - internal constructor( - rng: UniformRandomProvider, - state: LargeMeanPoissonSamplerState, - lambdaFractional: Double - ) { - require(!(lambdaFractional < 0 || lambdaFractional >= 1)) { "lambdaFractional must be in the range 0 (inclusive) to 1 (exclusive): $lambdaFractional" } - this.rng = rng - gaussian = - ZigguratNormalizedGaussianSampler(rng) - exponential = - AhrensDieterExponentialSampler.of( - rng, - 1.0 - ) - // Plain constructor uses the uncached function. - factorialLog = NO_CACHE_FACTORIAL_LOG!! - // Use the state to initialise the algorithm - lambda = state.lambdaRaw - logLambda = state.logLambda - logLambdaFactorial = state.logLambdaFactorial - delta = state.delta - halfDelta = state.halfDelta - twolpd = state.twolpd - p1 = state.p1 - p2 = state.p2 - c1 = state.c1 - - // The algorithm requires a Poisson sample from the remaining lambda fraction. - smallMeanPoissonSampler = - if (lambdaFractional < Double.MIN_VALUE) - NO_SMALL_MEAN_POISSON_SAMPLER - else // Not used. - KempSmallMeanPoissonSampler.of( - rng, - lambdaFractional - ) - } - - /** - * @param rng Generator of uniformly distributed random numbers. - * @param source Source to copy. - */ - private constructor( - rng: UniformRandomProvider, - source: LargeMeanPoissonSampler - ) { - this.rng = rng - gaussian = source.gaussian.withUniformRandomProvider(rng)!! - exponential = source.exponential.withUniformRandomProvider(rng)!! - // Reuse the cache - factorialLog = source.factorialLog - lambda = source.lambda - logLambda = source.logLambda - logLambdaFactorial = source.logLambdaFactorial - delta = source.delta - halfDelta = source.halfDelta - twolpd = source.twolpd - p1 = source.p1 - p2 = source.p2 - c1 = source.c1 - - // Share the state of the small sampler - smallMeanPoissonSampler = source.smallMeanPoissonSampler.withUniformRandomProvider(rng)!! - } - - /** {@inheritDoc} */ - override fun sample(): Int { - // This will never be null. It may be a no-op delegate that returns zero. - val y2: Int = smallMeanPoissonSampler.sample() - var x: Double - var y: Double - var v: Double - var a: Int - var t: Double - var qr: Double - var qa: Double - while (true) { - // Step 1: - val u = rng.nextDouble() - - if (u <= p1) { - // Step 2: - val n = gaussian.sample() - x = n * sqrt(lambda + halfDelta) - 0.5 - if (x > delta || x < -lambda) continue - y = if (x < 0) floor(x) else ceil(x) - val e = exponential.sample() - v = -e - 0.5 * n * n + c1 - } else { - // Step 3: - if (u > p1 + p2) { - y = lambda - break - } - - x = delta + twolpd / delta * exponential.sample() - y = ceil(x) - v = -exponential.sample() - delta * (x + 1) / twolpd - } - // The Squeeze Principle - // Step 4.1: - a = if (x < 0) 1 else 0 - t = y * (y + 1) / (2 * lambda) - - // Step 4.2 - if (v < -t && a == 0) { - y += lambda - break - } - - // Step 4.3: - qr = t * ((2 * y + 1) / (6 * lambda) - 1) - qa = qr - t * t / (3 * (lambda + a * (y + 1))) - - // Step 4.4: - if (v < qa) { - y += lambda - break - } - - // Step 4.5: - if (v > qr) continue - - // Step 4.6: - if (v < y * logLambda - getFactorialLog((y + lambda).toInt()) + logLambdaFactorial) { - y += lambda - break - } - } - - return min(y2 + y.toLong(), Int.MAX_VALUE.toLong()).toInt() - } - - - private fun getFactorialLog(n: Int): Double = factorialLog.value(n) - - override fun toString(): String = "Large Mean Poisson deviate [$rng]" - - override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateDiscreteSampler = - LargeMeanPoissonSampler(rng, this) - - val state: LargeMeanPoissonSamplerState - get() = LargeMeanPoissonSamplerState( - lambda, logLambda, logLambdaFactorial, - delta, halfDelta, twolpd, p1, p2, c1 - ) - - class LargeMeanPoissonSamplerState( - val lambdaRaw: Double, - val logLambda: Double, - val logLambdaFactorial: Double, - val delta: Double, - val halfDelta: Double, - val twolpd: Double, - val p1: Double, - val p2: Double, - val c1: Double - ) { - fun getLambda(): Int = lambdaRaw.toInt() - } - - companion object { - private const val MAX_MEAN = 0.5 * Int.MAX_VALUE - private var NO_CACHE_FACTORIAL_LOG: InternalUtils.FactorialLog? = null - - private val NO_SMALL_MEAN_POISSON_SAMPLER: SharedStateDiscreteSampler = - object : SharedStateDiscreteSampler { - override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateDiscreteSampler = -// No requirement for RNG - this - - override fun sample(): Int =// No Poisson sample - 0 - } - - fun of( - rng: UniformRandomProvider, - mean: Double - ): SharedStateDiscreteSampler = - LargeMeanPoissonSampler(rng, mean) - - init { - // Create without a cache. - NO_CACHE_FACTORIAL_LOG = - InternalUtils.FactorialLog.create() - } - } -} \ No newline at end of file diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt deleted file mode 100644 index c47b9b4e9..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/NormalizedGaussianSampler.kt +++ /dev/null @@ -1,4 +0,0 @@ -package scientifik.kmath.commons.rng.sampling.distribution - -interface NormalizedGaussianSampler : - ContinuousSampler diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/PoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/PoissonSampler.kt deleted file mode 100644 index a440c3a7d..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/PoissonSampler.kt +++ /dev/null @@ -1,40 +0,0 @@ -package scientifik.kmath.commons.rng.sampling.distribution - -import scientifik.kmath.commons.rng.UniformRandomProvider - -class PoissonSampler( - rng: UniformRandomProvider, - mean: Double -) : SamplerBase(null), - SharedStateDiscreteSampler { - private val poissonSamplerDelegate: SharedStateDiscreteSampler - - override fun sample(): Int = poissonSamplerDelegate.sample() - override fun toString(): String = poissonSamplerDelegate.toString() - - override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateDiscreteSampler? = -// Direct return of the optimised sampler - poissonSamplerDelegate.withUniformRandomProvider(rng) - - companion object { - const val PIVOT = 40.0 - - fun of( - rng: UniformRandomProvider, - mean: Double - ): SharedStateDiscreteSampler =// Each sampler should check the input arguments. - if (mean < PIVOT) SmallMeanPoissonSampler.of( - rng, - mean - ) else LargeMeanPoissonSampler.of( - rng, - mean - ) - } - - init { - // Delegate all work to specialised samplers. - poissonSamplerDelegate = - of(rng, mean) - } -} \ No newline at end of file diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SamplerBase.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SamplerBase.kt deleted file mode 100644 index 4170e9db3..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SamplerBase.kt +++ /dev/null @@ -1,12 +0,0 @@ -package scientifik.kmath.commons.rng.sampling.distribution - -import scientifik.kmath.commons.rng.UniformRandomProvider - -@Deprecated("Since version 1.1. Class intended for internal use only.") -open class SamplerBase protected constructor(private val rng: UniformRandomProvider?) { - protected fun nextDouble(): Double = rng!!.nextDouble() - protected fun nextInt(): Int = rng!!.nextInt() - protected fun nextInt(max: Int): Int = rng!!.nextInt(max) - protected fun nextLong(): Long = rng!!.nextLong() - override fun toString(): String = "rng=$rng" -} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt deleted file mode 100644 index c833ce8de..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateContinuousSampler.kt +++ /dev/null @@ -1,7 +0,0 @@ -package scientifik.kmath.commons.rng.sampling.distribution - -import scientifik.kmath.commons.rng.sampling.SharedStateSampler - -interface SharedStateContinuousSampler : ContinuousSampler, - SharedStateSampler { -} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt deleted file mode 100644 index 7b17e4670..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SharedStateDiscreteSampler.kt +++ /dev/null @@ -1,7 +0,0 @@ -package scientifik.kmath.commons.rng.sampling.distribution - -import scientifik.kmath.commons.rng.sampling.SharedStateSampler - -interface SharedStateDiscreteSampler : DiscreteSampler, - SharedStateSampler { // Composite interface -} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt deleted file mode 100644 index a35dd277c..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/SmallMeanPoissonSampler.kt +++ /dev/null @@ -1,60 +0,0 @@ -package scientifik.kmath.commons.rng.sampling.distribution - -import scientifik.kmath.commons.rng.UniformRandomProvider -import kotlin.math.ceil -import kotlin.math.exp - -class SmallMeanPoissonSampler : - SharedStateDiscreteSampler { - private val p0: Double - private val limit: Int - private val rng: UniformRandomProvider - - constructor( - rng: UniformRandomProvider, - mean: Double - ) { - this.rng = rng - require(mean > 0) { "mean is not strictly positive: $mean" } - p0 = exp(-mean) - - limit = (if (p0 > 0) ceil(1000 * mean) else throw IllegalArgumentException("No p(x=0) probability for mean: $mean")).toInt() - // This excludes NaN values for the mean - // else - // The returned sample is bounded by 1000 * mean - } - - private constructor( - rng: UniformRandomProvider, - source: SmallMeanPoissonSampler - ) { - this.rng = rng - p0 = source.p0 - limit = source.limit - } - - override fun sample(): Int { - var n = 0 - var r = 1.0 - - while (n < limit) { - r *= rng.nextDouble() - if (r >= p0) n++ else break - } - - return n - } - - override fun toString(): String = "Small Mean Poisson deviate [$rng]" - - override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateDiscreteSampler = - SmallMeanPoissonSampler(rng, this) - - companion object { - fun of( - rng: UniformRandomProvider, - mean: Double - ): SharedStateDiscreteSampler = - SmallMeanPoissonSampler(rng, mean) - } -} \ No newline at end of file diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt index 3b874adaa..a99052171 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt @@ -1,5 +1,6 @@ package scientifik.kmath.prob +import kotlinx.coroutines.flow.first import scientifik.kmath.chains.Chain import scientifik.kmath.chains.collect import scientifik.kmath.structures.Buffer @@ -69,6 +70,8 @@ fun Sampler.sampleBuffer( } } +suspend fun Sampler.next(generator: RandomGenerator) = sample(generator).first() + /** * Generate a bunch of samples from real distributions */ diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt index ea526c058..ae3f918ff 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt @@ -12,7 +12,6 @@ interface NamedDistribution : Distribution> * A multivariate distribution that has independent distributions for separate axis */ class FactorizedDistribution(val distributions: Collection>) : NamedDistribution { - override fun probability(arg: Map): Double { return distributions.fold(1.0) { acc, distr -> acc * distr.probability(arg) } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt index 2a225fe47..4b42db927 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt @@ -7,13 +7,11 @@ import kotlin.random.Random */ interface RandomGenerator { fun nextBoolean(): Boolean - fun nextDouble(): Double fun nextInt(): Int fun nextInt(until: Int): Int fun nextLong(): Long fun nextLong(until: Long): Long - fun fillBytes(array: ByteArray, fromIndex: Int = 0, toIndex: Int = array.size) fun nextBytes(size: Int): ByteArray = ByteArray(size).also { fillBytes(it) } @@ -28,21 +26,16 @@ interface RandomGenerator { companion object { val default by lazy { DefaultGenerator() } - fun default(seed: Long) = DefaultGenerator(Random(seed)) } } -inline class DefaultGenerator(val random: Random = Random) : RandomGenerator { +inline class DefaultGenerator(private val random: Random = Random) : RandomGenerator { override fun nextBoolean(): Boolean = random.nextBoolean() - override fun nextDouble(): Double = random.nextDouble() - override fun nextInt(): Int = random.nextInt() override fun nextInt(until: Int): Int = random.nextInt(until) - override fun nextLong(): Long = random.nextLong() - override fun nextLong(until: Long): Long = random.nextLong(until) override fun fillBytes(array: ByteArray, fromIndex: Int, toIndex: Int) { @@ -50,6 +43,5 @@ inline class DefaultGenerator(val random: Random = Random) : RandomGenerator { } override fun nextBytes(size: Int): ByteArray = random.nextBytes(size) - override fun fork(): RandomGenerator = RandomGenerator.default(random.nextLong()) } \ No newline at end of file diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt new file mode 100644 index 000000000..5dec2b641 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt @@ -0,0 +1,68 @@ +package scientifik.kmath.prob.samplers + +import scientifik.kmath.chains.Chain +import scientifik.kmath.prob.RandomGenerator +import scientifik.kmath.prob.Sampler +import scientifik.kmath.prob.chain +import kotlin.math.ln +import kotlin.math.pow + +class AhrensDieterExponentialSampler(val mean: Double) : Sampler { + init { + require(mean > 0) { "mean is not strictly positive: $mean" } + } + + override fun sample(generator: RandomGenerator): Chain = generator.chain { + // Step 1: + var a = 0.0 + var u = nextDouble() + + // Step 2 and 3: + while (u < 0.5) { + a += EXPONENTIAL_SA_QI[0] + u *= 2.0 + } + + // Step 4 (now u >= 0.5): + u += u - 1 + // Step 5: + if (u <= EXPONENTIAL_SA_QI[0]) return@chain mean * (a + u) + // Step 6: + var i = 0 // Should be 1, be we iterate before it in while using 0. + var u2 = nextDouble() + var umin = u2 + + // Step 7 and 8: + do { + ++i + u2 = nextDouble() + if (u2 < umin) umin = u2 + // Step 8: + } while (u > EXPONENTIAL_SA_QI[i]) // Ensured to exit since EXPONENTIAL_SA_QI[MAX] = 1. + + mean * (a + umin * EXPONENTIAL_SA_QI[0]) + } + + override fun toString(): String = "Ahrens-Dieter Exponential deviate" + + companion object { + private val EXPONENTIAL_SA_QI = DoubleArray(16) + + fun of(mean: Double): Sampler = + AhrensDieterExponentialSampler(mean) + + init { + /** + * Filling EXPONENTIAL_SA_QI table. + * Note that we don't want qi = 0 in the table. + */ + val ln2 = ln(2.0) + var qi = 0.0 + + EXPONENTIAL_SA_QI.indices.forEach { i -> + qi += ln2.pow(i + 1.0) / InternalUtils.factorial(i + 1) + EXPONENTIAL_SA_QI[i] = qi + } + } + } +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt new file mode 100644 index 000000000..3235b06f5 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt @@ -0,0 +1,37 @@ +package scientifik.kmath.prob.samplers + +import scientifik.kmath.chains.Chain +import scientifik.kmath.prob.RandomGenerator +import scientifik.kmath.prob.Sampler +import scientifik.kmath.prob.chain +import kotlin.math.* + +class BoxMullerNormalizedGaussianSampler : NormalizedGaussianSampler, Sampler { + private var nextGaussian: Double = Double.NaN + + override fun sample(generator: RandomGenerator): Chain = generator.chain { + val random: Double + + if (nextGaussian.isNaN()) { + // Generate a pair of Gaussian numbers. + val x = nextDouble() + val y = nextDouble() + val alpha = 2 * PI * x + val r = sqrt(-2 * ln(y)) + // Return the first element of the generated pair. + random = r * cos(alpha) + // Keep second element of the pair for next invocation. + nextGaussian = r * sin(alpha) + } else { + // Use the second element of the pair (generated at the + // previous invocation). + random = nextGaussian + // Both elements of the pair have been used. + nextGaussian = Double.NaN + } + + random + } + + override fun toString(): String = "Box-Muller normalized Gaussian deviate" +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt new file mode 100644 index 000000000..0c984ab6a --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt @@ -0,0 +1,34 @@ +package scientifik.kmath.prob.samplers + +import scientifik.kmath.chains.Chain +import scientifik.kmath.chains.map +import scientifik.kmath.prob.RandomGenerator +import scientifik.kmath.prob.Sampler + +class GaussianSampler( + private val mean: Double, + private val standardDeviation: Double, + private val normalized: NormalizedGaussianSampler +) : Sampler { + + init { + require(standardDeviation > 0) { "standard deviation is not strictly positive: $standardDeviation" } + } + + override fun sample(generator: RandomGenerator): Chain = + normalized.sample(generator).map { standardDeviation * it + mean } + + override fun toString(): String = "Gaussian deviate [$normalized]" + + companion object { + fun of( + normalized: NormalizedGaussianSampler, + mean: Double, + standardDeviation: Double + ) = GaussianSampler( + mean, + standardDeviation, + normalized + ) + } +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/InternalGamma.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalGamma.kt similarity index 93% rename from kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/InternalGamma.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalGamma.kt index 79426d7ae..50c5f4ce0 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/InternalGamma.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalGamma.kt @@ -1,10 +1,10 @@ -package scientifik.kmath.commons.rng.sampling.distribution +package scientifik.kmath.prob.samplers import kotlin.math.PI import kotlin.math.ln internal object InternalGamma { - const val LANCZOS_G = 607.0 / 128.0 + private const val LANCZOS_G = 607.0 / 128.0 private val LANCZOS_COEFFICIENTS = doubleArrayOf( 0.99999999999999709182, diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/InternalUtils.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalUtils.kt similarity index 55% rename from kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/InternalUtils.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalUtils.kt index 0f563b956..f2f1b3865 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/InternalUtils.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalUtils.kt @@ -1,7 +1,5 @@ -package scientifik.kmath.commons.rng.sampling.distribution +package scientifik.kmath.prob.samplers -import scientifik.kmath.commons.rng.UniformRandomProvider -import scientifik.kmath.commons.rng.sampling.SharedStateSampler import kotlin.math.ln import kotlin.math.min @@ -20,8 +18,8 @@ internal object InternalUtils { fun factorial(n: Int): Long = FACTORIALS[n] - fun validateProbabilities(probabilities: DoubleArray?): Double { - require(!(probabilities == null || probabilities.isEmpty())) { "Probabilities must not be empty." } + fun validateProbabilities(probabilities: DoubleArray): Double { + require(probabilities.isNotEmpty()) { "Probabilities must not be empty." } var sumProb = 0.0 probabilities.forEach { prob -> @@ -33,23 +31,10 @@ internal object InternalUtils { return sumProb } - fun validateProbability(probability: Double): Unit = - require(!(probability < 0 || probability.isInfinite() || probability.isNaN())) { "Invalid probability: $probability" } - - fun newNormalizedGaussianSampler( - sampler: NormalizedGaussianSampler, - rng: UniformRandomProvider - ): NormalizedGaussianSampler { - if (sampler !is SharedStateSampler<*>) throw UnsupportedOperationException("The underlying sampler cannot share state") - - val newSampler: Any = - (sampler as SharedStateSampler<*>).withUniformRandomProvider(rng) as? NormalizedGaussianSampler - ?: throw UnsupportedOperationException( - "The underlying sampler did not create a normalized Gaussian sampler" - ) - - return newSampler as NormalizedGaussianSampler - } + private fun validateProbability(probability: Double): Unit = + require(!(probability < 0 || probability.isInfinite() || probability.isNaN())) { + "Invalid probability: $probability" + } class FactorialLog private constructor( numValues: Int, @@ -68,23 +53,19 @@ internal object InternalUtils { BEGIN_LOG_FACTORIALS, endCopy) } // All values to be computed - else - endCopy = - BEGIN_LOG_FACTORIALS + else endCopy = BEGIN_LOG_FACTORIALS // Compute remaining values. (endCopy until numValues).forEach { i -> - if (i < FACTORIALS.size) logFactorials[i] = ln( - FACTORIALS[i].toDouble()) else logFactorials[i] = - logFactorials[i - 1] + ln(i.toDouble()) + if (i < FACTORIALS.size) + logFactorials[i] = ln(FACTORIALS[i].toDouble()) + else + logFactorials[i] = logFactorials[i - 1] + ln(i.toDouble()) } } fun withCache(cacheSize: Int): FactorialLog = - FactorialLog( - cacheSize, - logFactorials - ) + FactorialLog(cacheSize, logFactorials) fun value(n: Int): Double { if (n < logFactorials.size) @@ -98,10 +79,7 @@ internal object InternalUtils { companion object { fun create(): FactorialLog = - FactorialLog( - 0, - null - ) + FactorialLog(0, null) } } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt similarity index 66% rename from kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt index 3072cf020..cdd4c4cd1 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt @@ -1,14 +1,16 @@ -package scientifik.kmath.commons.rng.sampling.distribution +package scientifik.kmath.prob.samplers -import scientifik.kmath.commons.rng.UniformRandomProvider +import scientifik.kmath.chains.Chain +import scientifik.kmath.prob.RandomGenerator +import scientifik.kmath.prob.Sampler +import scientifik.kmath.prob.chain import kotlin.math.exp class KempSmallMeanPoissonSampler private constructor( - private val rng: UniformRandomProvider, private val p0: Double, private val mean: Double -) : SharedStateDiscreteSampler { - override fun sample(): Int { +) : Sampler { + override fun sample(generator: RandomGenerator): Chain = generator.chain { // Note on the algorithm: // - X is the unknown sample deviate (the output of the algorithm) // - x is the current value from the distribution @@ -16,7 +18,7 @@ class KempSmallMeanPoissonSampler private constructor( // - u is effectively the cumulative probability that the sample X // is equal or above the current value x, p(X>=x) // So if p(X>=x) > p(X=x) the sample must be above x, otherwise it is x - var u = rng.nextDouble() + var u = nextDouble() var x = 0 var p = p0 @@ -28,31 +30,20 @@ class KempSmallMeanPoissonSampler private constructor( // The algorithm listed in Kemp (1981) does not check that the rolling probability // is positive. This check is added to ensure no errors when the limit of the summation // 1 - sum(p(x)) is above 0 due to cumulative error in floating point arithmetic. - if (p == 0.0) return x + if (p == 0.0) return@chain x } - return x + x } - override fun toString(): String = "Kemp Small Mean Poisson deviate [$rng]" - - override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateDiscreteSampler = - KempSmallMeanPoissonSampler(rng, p0, mean) + override fun toString(): String = "Kemp Small Mean Poisson deviate" companion object { - fun of( - rng: UniformRandomProvider, - mean: Double - ): SharedStateDiscreteSampler { + fun of(mean: Double): KempSmallMeanPoissonSampler { require(mean > 0) { "Mean is not strictly positive: $mean" } val p0: Double = exp(-mean) - // Probability must be positive. As mean increases then p(0) decreases. - if (p0 > 0) return KempSmallMeanPoissonSampler( - rng, - p0, - mean - ) + if (p0 > 0) return KempSmallMeanPoissonSampler(p0, mean) throw IllegalArgumentException("No probability for mean: $mean") } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt new file mode 100644 index 000000000..33b1b3f8a --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt @@ -0,0 +1,132 @@ +package scientifik.kmath.prob.samplers + +import kotlinx.coroutines.flow.first +import scientifik.kmath.chains.Chain +import scientifik.kmath.chains.ConstantChain +import scientifik.kmath.chains.SimpleChain +import scientifik.kmath.prob.RandomGenerator +import scientifik.kmath.prob.Sampler +import scientifik.kmath.prob.next +import kotlin.math.* + +class LargeMeanPoissonSampler(val mean: Double) : Sampler { + private val exponential: Sampler = + AhrensDieterExponentialSampler.of(1.0) + private val gaussian: Sampler = + ZigguratNormalizedGaussianSampler() + private val factorialLog: InternalUtils.FactorialLog = NO_CACHE_FACTORIAL_LOG!! + private val lambda: Double = floor(mean) + private val logLambda: Double = ln(lambda) + private val logLambdaFactorial: Double = getFactorialLog(lambda.toInt()) + private val delta: Double = sqrt(lambda * ln(32 * lambda / PI + 1)) + private val halfDelta: Double = delta / 2 + private val twolpd: Double = 2 * lambda + delta + private val c1: Double = 1 / (8 * lambda) + private val a1: Double = sqrt(PI * twolpd) * exp(c1) + private val a2: Double = twolpd / delta * exp(-delta * (1 + delta) / twolpd) + private val aSum: Double = a1 + a2 + 1 + private val p1: Double = a1 / aSum + private val p2: Double = a2 / aSum + + private val smallMeanPoissonSampler: Sampler = if (mean - lambda < Double.MIN_VALUE) + NO_SMALL_MEAN_POISSON_SAMPLER + else // Not used. + KempSmallMeanPoissonSampler.of(mean - lambda) + + init { + require(mean >= 1) { "mean is not >= 1: $mean" } + // The algorithm is not valid if Math.floor(mean) is not an integer. + require(mean <= MAX_MEAN) { "mean $mean > $MAX_MEAN" } + } + + override fun sample(generator: RandomGenerator): Chain = SimpleChain { + // This will never be null. It may be a no-op delegate that returns zero. + val y2 = smallMeanPoissonSampler.next(generator) + var x: Double + var y: Double + var v: Double + var a: Int + var t: Double + var qr: Double + var qa: Double + + while (true) { + // Step 1: + val u = generator.nextDouble() + + if (u <= p1) { + // Step 2: + val n = gaussian.next(generator) + x = n * sqrt(lambda + halfDelta) - 0.5 + if (x > delta || x < -lambda) continue + y = if (x < 0) floor(x) else ceil(x) + val e = exponential.next(generator) + v = -e - 0.5 * n * n + c1 + } else { + // Step 3: + if (u > p1 + p2) { + y = lambda + break + } + + x = delta + twolpd / delta * exponential.next(generator) + y = ceil(x) + v = -exponential.next(generator) - delta * (x + 1) / twolpd + } + + // The Squeeze Principle + // Step 4.1: + a = if (x < 0) 1 else 0 + t = y * (y + 1) / (2 * lambda) + + // Step 4.2 + if (v < -t && a == 0) { + y += lambda + break + } + + // Step 4.3: + qr = t * ((2 * y + 1) / (6 * lambda) - 1) + qa = qr - t * t / (3 * (lambda + a * (y + 1))) + + // Step 4.4: + if (v < qa) { + y += lambda + break + } + + // Step 4.5: + if (v > qr) continue + + // Step 4.6: + if (v < y * logLambda - getFactorialLog((y + lambda).toInt()) + logLambdaFactorial) { + y += lambda + break + } + } + + min(y2 + y.toLong(), Int.MAX_VALUE.toLong()).toInt() + } + + private fun getFactorialLog(n: Int): Double = factorialLog.value(n) + + override fun toString(): String = "Large Mean Poisson deviate" + + companion object { + private const val MAX_MEAN = 0.5 * Int.MAX_VALUE + private var NO_CACHE_FACTORIAL_LOG: InternalUtils.FactorialLog? = null + + private val NO_SMALL_MEAN_POISSON_SAMPLER = object : Sampler { + override fun sample(generator: RandomGenerator): Chain = ConstantChain(0) + } + + fun of(mean: Double): LargeMeanPoissonSampler = + LargeMeanPoissonSampler(mean) + + init { + // Create without a cache. + NO_CACHE_FACTORIAL_LOG = + InternalUtils.FactorialLog.create() + } + } +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt similarity index 53% rename from kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt index ee346718e..c44943056 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt @@ -1,35 +1,42 @@ -package scientifik.kmath.commons.rng.sampling.distribution +package scientifik.kmath.prob.samplers -import scientifik.kmath.commons.rng.UniformRandomProvider +import scientifik.kmath.chains.Chain +import scientifik.kmath.prob.RandomGenerator +import scientifik.kmath.prob.Sampler +import scientifik.kmath.prob.chain import kotlin.math.ln import kotlin.math.sqrt -class MarsagliaNormalizedGaussianSampler(private val rng: UniformRandomProvider) : - NormalizedGaussianSampler, - SharedStateContinuousSampler { +class MarsagliaNormalizedGaussianSampler : NormalizedGaussianSampler, Sampler { private var nextGaussian = Double.NaN - override fun sample(): Double { + override fun sample(generator: RandomGenerator): Chain = generator.chain { if (nextGaussian.isNaN()) { + val alpha: Double + var x: Double + // Rejection scheme for selecting a pair that lies within the unit circle. while (true) { // Generate a pair of numbers within [-1 , 1). - val x = 2.0 * rng.nextDouble() - 1.0 - val y = 2.0 * rng.nextDouble() - 1.0 + x = 2.0 * generator.nextDouble() - 1.0 + val y = 2.0 * generator.nextDouble() - 1.0 val r2 = x * x + y * y + if (r2 < 1 && r2 > 0) { // Pair (x, y) is within unit circle. - val alpha = sqrt(-2 * ln(r2) / r2) + alpha = sqrt(-2 * ln(r2) / r2) // Keep second element of the pair for next invocation. nextGaussian = alpha * y // Return the first element of the generated pair. - return alpha * x + break } - // Pair is not within the unit circle: Generate another one. } + + // Return the first element of the generated pair. + alpha * x } else { // Use the second element of the pair (generated at the // previous invocation). @@ -37,18 +44,9 @@ class MarsagliaNormalizedGaussianSampler(private val rng: UniformRandomProvider) // Both elements of the pair have been used. nextGaussian = Double.NaN - return r + r } } - override fun toString(): String = "Box-Muller (with rejection) normalized Gaussian deviate [$rng]" - - override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateContinuousSampler = - MarsagliaNormalizedGaussianSampler(rng) - - companion object { - @Suppress("UNCHECKED_CAST") - fun of(rng: UniformRandomProvider): S where S : NormalizedGaussianSampler?, S : SharedStateContinuousSampler? = - MarsagliaNormalizedGaussianSampler(rng) as S - } + override fun toString(): String = "Box-Muller (with rejection) normalized Gaussian deviate" } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/NormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/NormalizedGaussianSampler.kt new file mode 100644 index 000000000..0e5d6db59 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/NormalizedGaussianSampler.kt @@ -0,0 +1,5 @@ +package scientifik.kmath.prob.samplers + +import scientifik.kmath.prob.Sampler + +interface NormalizedGaussianSampler : Sampler diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/PoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/PoissonSampler.kt new file mode 100644 index 000000000..d3c53fbb4 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/PoissonSampler.kt @@ -0,0 +1,29 @@ +package scientifik.kmath.prob.samplers + +import scientifik.kmath.chains.Chain +import scientifik.kmath.prob.RandomGenerator +import scientifik.kmath.prob.Sampler + + +class PoissonSampler( + mean: Double +) : Sampler { + private val poissonSamplerDelegate: Sampler + + init { + // Delegate all work to specialised samplers. + poissonSamplerDelegate = of(mean) + } + + override fun sample(generator: RandomGenerator): Chain = poissonSamplerDelegate.sample(generator) + override fun toString(): String = poissonSamplerDelegate.toString() + + companion object { + private const val PIVOT = 40.0 + + fun of(mean: Double) =// Each sampler should check the input arguments. + if (mean < PIVOT) SmallMeanPoissonSampler.of( + mean + ) else LargeMeanPoissonSampler.of(mean) + } +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt new file mode 100644 index 000000000..6509563dd --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt @@ -0,0 +1,43 @@ +package scientifik.kmath.prob.samplers + +import scientifik.kmath.chains.Chain +import scientifik.kmath.chains.SimpleChain +import scientifik.kmath.prob.RandomGenerator +import scientifik.kmath.prob.Sampler +import scientifik.kmath.prob.chain +import kotlin.math.ceil +import kotlin.math.exp + +class SmallMeanPoissonSampler(mean: Double) : Sampler { + private val p0: Double + private val limit: Int + + init { + require(mean > 0) { "mean is not strictly positive: $mean" } + p0 = exp(-mean) + + limit = (if (p0 > 0) + ceil(1000 * mean) + else + throw IllegalArgumentException("No p(x=0) probability for mean: $mean")).toInt() + } + + override fun sample(generator: RandomGenerator): Chain = generator.chain { + var n = 0 + var r = 1.0 + + while (n < limit) { + r *= nextDouble() + if (r >= p0) n++ else break + } + + n + } + + override fun toString(): String = "Small Mean Poisson deviate" + + companion object { + fun of(mean: Double): SmallMeanPoissonSampler = + SmallMeanPoissonSampler(mean) + } +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt similarity index 58% rename from kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt rename to kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt index 26e089599..57e7fc47e 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt @@ -1,38 +1,76 @@ -package scientifik.kmath.commons.rng.sampling.distribution +package scientifik.kmath.prob.samplers -import scientifik.kmath.commons.rng.UniformRandomProvider +import scientifik.kmath.chains.Chain +import scientifik.kmath.chains.SimpleChain +import scientifik.kmath.prob.RandomGenerator +import scientifik.kmath.prob.Sampler +import scientifik.kmath.prob.chain import kotlin.math.* -class ZigguratNormalizedGaussianSampler(private val rng: UniformRandomProvider) : - NormalizedGaussianSampler, - SharedStateContinuousSampler { +class ZigguratNormalizedGaussianSampler() : + NormalizedGaussianSampler, Sampler { + + private fun sampleOne(generator: RandomGenerator): Double { + val j = generator.nextLong() + val i = (j and LAST.toLong()).toInt() + return if (abs(j) < K[i]) j * W[i] else fix(generator, j, i) + } + + override fun sample(generator: RandomGenerator): Chain = generator.chain { sampleOne(this) } + + override fun toString(): String = "Ziggurat normalized Gaussian deviate" + + private fun fix( + generator: RandomGenerator, + hz: Long, + iz: Int + ): Double { + var x: Double + var y: Double + x = hz * W[iz] + + return if (iz == 0) { + // Base strip. + // This branch is called about 5.7624515E-4 times per sample. + do { + y = -ln(generator.nextDouble()) + x = -ln(generator.nextDouble()) * ONE_OVER_R + } while (y + y < x * x) + + val out = R + x + if (hz > 0) out else -out + } else { + // Wedge of other strips. + // This branch is called about 0.027323 times per sample. + // else + // Try again. + // This branch is called about 0.012362 times per sample. + if (F[iz] + generator.nextDouble() * (F[iz - 1] - F[iz]) < gauss( + x + ) + ) x else sampleOne(generator) + } + } companion object { - private const val R = 3.442619855899 + private const val R: Double = 3.442619855899 private const val ONE_OVER_R: Double = 1 / R private const val V = 9.91256303526217e-3 private val MAX: Double = 2.0.pow(63.0) private val ONE_OVER_MAX: Double = 1.0 / MAX - private const val LEN = 128 + private const val LEN: Int = 128 private const val LAST: Int = LEN - 1 - private val K = LongArray(LEN) - private val W = DoubleArray(LEN) - private val F = DoubleArray(LEN) + private val K: LongArray = LongArray(LEN) + private val W: DoubleArray = DoubleArray(LEN) + private val F: DoubleArray = DoubleArray(LEN) private fun gauss(x: Double): Double = exp(-0.5 * x * x) - @Suppress("UNCHECKED_CAST") - fun of(rng: UniformRandomProvider): S where S : NormalizedGaussianSampler?, S : SharedStateContinuousSampler? = - ZigguratNormalizedGaussianSampler(rng) as S - init { // Filling the tables. - var d = - R + var d = R var t = d var fd = - gauss( - d - ) + gauss(d) val q = V / fd K[0] = (d / q * MAX).toLong() K[1] = 0 @@ -54,46 +92,4 @@ class ZigguratNormalizedGaussianSampler(private val rng: UniformRandomProvider) } } } - - override fun sample(): Double { - val j = rng.nextLong() - val i = (j and LAST.toLong()).toInt() - return if (abs(j) < K[i]) j * W[i] else fix(j, i) - } - - override fun toString(): String = "Ziggurat normalized Gaussian deviate [$rng]" - - private fun fix( - hz: Long, - iz: Int - ): Double { - var x: Double - var y: Double - x = hz * W[iz] - - return if (iz == 0) { - // Base strip. - // This branch is called about 5.7624515E-4 times per sample. - do { - y = -ln(rng.nextDouble()) - x = -ln(rng.nextDouble()) * ONE_OVER_R - } while (y + y < x * x) - - val out = R + x - if (hz > 0) out else -out - } else { - // Wedge of other strips. - // This branch is called about 0.027323 times per sample. - // else - // Try again. - // This branch is called about 0.012362 times per sample. - if (F[iz] + rng.nextDouble() * (F[iz - 1] - F[iz]) < gauss( - x - ) - ) x else sample() - } - } - - override fun withUniformRandomProvider(rng: UniformRandomProvider): SharedStateContinuousSampler = - ZigguratNormalizedGaussianSampler(rng) } diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/DistributionsJVM.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/DistributionsJVM.kt deleted file mode 100644 index 649cae961..000000000 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/DistributionsJVM.kt +++ /dev/null @@ -1,66 +0,0 @@ -package scientifik.kmath.prob - -import scientifik.kmath.commons.rng.sampling.distribution.ContinuousSampler -import scientifik.kmath.commons.rng.sampling.distribution.DiscreteSampler -import scientifik.kmath.commons.rng.sampling.distribution.GaussianSampler -import scientifik.kmath.commons.rng.sampling.distribution.PoissonSampler -import kotlin.math.PI -import kotlin.math.exp -import kotlin.math.pow -import kotlin.math.sqrt - -fun Distribution.Companion.normal( - method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat -): Distribution = object : ContinuousSamplerDistribution() { - override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler { - val provider = generator.asUniformRandomProvider() - return normalSampler(method, provider) - } - - override fun probability(arg: Double): Double { - return exp(-arg.pow(2) / 2) / sqrt(PI * 2) - } -} - -fun Distribution.Companion.normal( - mean: Double, - sigma: Double, - method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat -): ContinuousSamplerDistribution = object : ContinuousSamplerDistribution() { - private val sigma2 = sigma.pow(2) - private val norm = sigma * sqrt(PI * 2) - - override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler { - val provider = generator.asUniformRandomProvider() - val normalizedSampler = normalSampler(method, provider) - return GaussianSampler( - normalizedSampler, - mean, - sigma - ) - } - - override fun probability(arg: Double): Double { - return exp(-(arg - mean).pow(2) / 2 / sigma2) / norm - } -} - -fun Distribution.Companion.poisson( - lambda: Double -): DiscreteSamplerDistribution = object : DiscreteSamplerDistribution() { - - override fun buildSampler(generator: RandomGenerator): DiscreteSampler { - return PoissonSampler.of(generator.asUniformRandomProvider(), lambda) - } - - private val computedProb: HashMap = hashMapOf(0 to exp(-lambda)) - - override fun probability(arg: Int): Double { - require(arg >= 0) { "The argument must be >= 0" } - - return if (arg > 40) - exp(-(arg - lambda).pow(2) / 2 / lambda) / sqrt(2 * PI * lambda) - else - computedProb.getOrPut(arg) { probability(arg - 1) * lambda / arg } - } -} diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt index 4c8d630ae..797c932ad 100644 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt +++ b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt @@ -1,11 +1,10 @@ package scientifik.kmath.prob import org.apache.commons.rng.simple.RandomSource -import scientifik.kmath.commons.rng.UniformRandomProvider -class RandomSourceGenerator(val source: RandomSource, seed: Long?) : +class RandomSourceGenerator(private val source: RandomSource, seed: Long?) : RandomGenerator { - internal val random = seed?.let { + private val random = seed?.let { RandomSource.create(source, seed) } ?: RandomSource.create(source) @@ -24,24 +23,6 @@ class RandomSourceGenerator(val source: RandomSource, seed: Long?) : override fun fork(): RandomGenerator = RandomSourceGenerator(source, nextLong()) } -/** - * Represent this [RandomGenerator] as commons-rng [UniformRandomProvider] preserving and mirroring its current state. - * Getting new value from one of those changes the state of another. - */ -fun RandomGenerator.asUniformRandomProvider(): UniformRandomProvider = if (this is RandomSourceGenerator) { - object : UniformRandomProvider { - override fun nextBytes(bytes: ByteArray) = random.nextBytes(bytes) - override fun nextBytes(bytes: ByteArray, start: Int, len: Int) = random.nextBytes(bytes, start, len) - override fun nextInt(): Int = random.nextInt() - override fun nextInt(n: Int): Int = random.nextInt(n) - override fun nextLong(): Long = random.nextLong() - override fun nextLong(n: Long): Long = random.nextLong(n) - override fun nextBoolean(): Boolean = random.nextBoolean() - override fun nextFloat(): Float = random.nextFloat() - override fun nextDouble(): Double = random.nextDouble() - } -} else RandomGeneratorProvider(this) - fun RandomGenerator.Companion.fromSource(source: RandomSource, seed: Long? = null): RandomSourceGenerator = RandomSourceGenerator(source, seed) From e7b1203c2ddca46225c9714d86856365d906b029 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 8 Jun 2020 17:29:57 +0700 Subject: [PATCH 004/393] Move init blocks checks to factory method of and make all the samplers' constructor private --- .../AhrensDieterExponentialSampler.kt | 16 ++++----- .../BoxMullerNormalizedGaussianSampler.kt | 6 +++- .../kmath/prob/samplers/GaussianSampler.kt | 25 +++++++------- .../samplers/KempSmallMeanPoissonSampler.kt | 6 ++-- .../prob/samplers/LargeMeanPoissonSampler.kt | 33 +++++++------------ .../MarsagliaNormalizedGaussianSampler.kt | 6 +++- .../kmath/prob/samplers/PoissonSampler.kt | 14 ++------ .../prob/samplers/SmallMeanPoissonSampler.kt | 24 ++++++-------- .../ZigguratNormalizedGaussianSampler.kt | 6 ++-- 9 files changed, 60 insertions(+), 76 deletions(-) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt index 5dec2b641..794c1010d 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt @@ -7,11 +7,7 @@ import scientifik.kmath.prob.chain import kotlin.math.ln import kotlin.math.pow -class AhrensDieterExponentialSampler(val mean: Double) : Sampler { - init { - require(mean > 0) { "mean is not strictly positive: $mean" } - } - +class AhrensDieterExponentialSampler private constructor(val mean: Double) : Sampler { override fun sample(generator: RandomGenerator): Chain = generator.chain { // Step 1: var a = 0.0 @@ -46,10 +42,7 @@ class AhrensDieterExponentialSampler(val mean: Double) : Sampler { override fun toString(): String = "Ahrens-Dieter Exponential deviate" companion object { - private val EXPONENTIAL_SA_QI = DoubleArray(16) - - fun of(mean: Double): Sampler = - AhrensDieterExponentialSampler(mean) + private val EXPONENTIAL_SA_QI by lazy { DoubleArray(16) } init { /** @@ -64,5 +57,10 @@ class AhrensDieterExponentialSampler(val mean: Double) : Sampler { EXPONENTIAL_SA_QI[i] = qi } } + + fun of(mean: Double): AhrensDieterExponentialSampler { + require(mean > 0) { "mean is not strictly positive: $mean" } + return AhrensDieterExponentialSampler(mean) + } } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt index 3235b06f5..57c38d6b7 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt @@ -6,7 +6,7 @@ import scientifik.kmath.prob.Sampler import scientifik.kmath.prob.chain import kotlin.math.* -class BoxMullerNormalizedGaussianSampler : NormalizedGaussianSampler, Sampler { +class BoxMullerNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { private var nextGaussian: Double = Double.NaN override fun sample(generator: RandomGenerator): Chain = generator.chain { @@ -34,4 +34,8 @@ class BoxMullerNormalizedGaussianSampler : NormalizedGaussianSampler, Sampler { - - init { - require(standardDeviation > 0) { "standard deviation is not strictly positive: $standardDeviation" } - } - override fun sample(generator: RandomGenerator): Chain = normalized.sample(generator).map { standardDeviation * it + mean } @@ -22,13 +17,17 @@ class GaussianSampler( companion object { fun of( - normalized: NormalizedGaussianSampler, mean: Double, - standardDeviation: Double - ) = GaussianSampler( - mean, - standardDeviation, - normalized - ) + standardDeviation: Double, + normalized: NormalizedGaussianSampler + ): GaussianSampler { + require(standardDeviation > 0) { "standard deviation is not strictly positive: $standardDeviation" } + + return GaussianSampler( + mean, + standardDeviation, + normalized + ) + } } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt index cdd4c4cd1..65e762b68 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt @@ -41,10 +41,10 @@ class KempSmallMeanPoissonSampler private constructor( companion object { fun of(mean: Double): KempSmallMeanPoissonSampler { require(mean > 0) { "Mean is not strictly positive: $mean" } - val p0: Double = exp(-mean) + val p0 = exp(-mean) // Probability must be positive. As mean increases then p(0) decreases. - if (p0 > 0) return KempSmallMeanPoissonSampler(p0, mean) - throw IllegalArgumentException("No probability for mean: $mean") + require(p0 > 0) { "No probability for mean: $mean" } + return KempSmallMeanPoissonSampler(p0, mean) } } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt index 33b1b3f8a..39a3dc168 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt @@ -1,6 +1,5 @@ package scientifik.kmath.prob.samplers -import kotlinx.coroutines.flow.first import scientifik.kmath.chains.Chain import scientifik.kmath.chains.ConstantChain import scientifik.kmath.chains.SimpleChain @@ -9,12 +8,10 @@ import scientifik.kmath.prob.Sampler import scientifik.kmath.prob.next import kotlin.math.* -class LargeMeanPoissonSampler(val mean: Double) : Sampler { - private val exponential: Sampler = - AhrensDieterExponentialSampler.of(1.0) - private val gaussian: Sampler = - ZigguratNormalizedGaussianSampler() - private val factorialLog: InternalUtils.FactorialLog = NO_CACHE_FACTORIAL_LOG!! +class LargeMeanPoissonSampler private constructor(val mean: Double) : Sampler { + private val exponential: Sampler = AhrensDieterExponentialSampler.of(1.0) + private val gaussian: Sampler = ZigguratNormalizedGaussianSampler() + private val factorialLog: InternalUtils.FactorialLog = NO_CACHE_FACTORIAL_LOG private val lambda: Double = floor(mean) private val logLambda: Double = ln(lambda) private val logLambdaFactorial: Double = getFactorialLog(lambda.toInt()) @@ -33,12 +30,6 @@ class LargeMeanPoissonSampler(val mean: Double) : Sampler { else // Not used. KempSmallMeanPoissonSampler.of(mean - lambda) - init { - require(mean >= 1) { "mean is not >= 1: $mean" } - // The algorithm is not valid if Math.floor(mean) is not an integer. - require(mean <= MAX_MEAN) { "mean $mean > $MAX_MEAN" } - } - override fun sample(generator: RandomGenerator): Chain = SimpleChain { // This will never be null. It may be a no-op delegate that returns zero. val y2 = smallMeanPoissonSampler.next(generator) @@ -113,20 +104,18 @@ class LargeMeanPoissonSampler(val mean: Double) : Sampler { override fun toString(): String = "Large Mean Poisson deviate" companion object { - private const val MAX_MEAN = 0.5 * Int.MAX_VALUE - private var NO_CACHE_FACTORIAL_LOG: InternalUtils.FactorialLog? = null + private const val MAX_MEAN: Double = 0.5 * Int.MAX_VALUE + private val NO_CACHE_FACTORIAL_LOG: InternalUtils.FactorialLog = InternalUtils.FactorialLog.create() private val NO_SMALL_MEAN_POISSON_SAMPLER = object : Sampler { override fun sample(generator: RandomGenerator): Chain = ConstantChain(0) } - fun of(mean: Double): LargeMeanPoissonSampler = - LargeMeanPoissonSampler(mean) - - init { - // Create without a cache. - NO_CACHE_FACTORIAL_LOG = - InternalUtils.FactorialLog.create() + fun of(mean: Double): LargeMeanPoissonSampler { + require(mean >= 1) { "mean is not >= 1: $mean" } + // The algorithm is not valid if Math.floor(mean) is not an integer. + require(mean <= MAX_MEAN) { "mean $mean > $MAX_MEAN" } + return LargeMeanPoissonSampler(mean) } } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt index c44943056..dd8f82a2c 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt @@ -7,7 +7,7 @@ import scientifik.kmath.prob.chain import kotlin.math.ln import kotlin.math.sqrt -class MarsagliaNormalizedGaussianSampler : NormalizedGaussianSampler, Sampler { +class MarsagliaNormalizedGaussianSampler private constructor(): NormalizedGaussianSampler, Sampler { private var nextGaussian = Double.NaN override fun sample(generator: RandomGenerator): Chain = generator.chain { @@ -49,4 +49,8 @@ class MarsagliaNormalizedGaussianSampler : NormalizedGaussianSampler, Sampler { - private val poissonSamplerDelegate: Sampler - - init { - // Delegate all work to specialised samplers. - poissonSamplerDelegate = of(mean) - } - + private val poissonSamplerDelegate: Sampler = of(mean) override fun sample(generator: RandomGenerator): Chain = poissonSamplerDelegate.sample(generator) override fun toString(): String = poissonSamplerDelegate.toString() @@ -22,8 +16,6 @@ class PoissonSampler( private const val PIVOT = 40.0 fun of(mean: Double) =// Each sampler should check the input arguments. - if (mean < PIVOT) SmallMeanPoissonSampler.of( - mean - ) else LargeMeanPoissonSampler.of(mean) + if (mean < PIVOT) SmallMeanPoissonSampler.of(mean) else LargeMeanPoissonSampler.of(mean) } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt index 6509563dd..7022b0f3a 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt @@ -8,19 +8,13 @@ import scientifik.kmath.prob.chain import kotlin.math.ceil import kotlin.math.exp -class SmallMeanPoissonSampler(mean: Double) : Sampler { - private val p0: Double - private val limit: Int +class SmallMeanPoissonSampler private constructor(mean: Double) : Sampler { + private val p0: Double = exp(-mean) - init { - require(mean > 0) { "mean is not strictly positive: $mean" } - p0 = exp(-mean) - - limit = (if (p0 > 0) - ceil(1000 * mean) - else - throw IllegalArgumentException("No p(x=0) probability for mean: $mean")).toInt() - } + private val limit: Int = (if (p0 > 0) + ceil(1000 * mean) + else + throw IllegalArgumentException("No p(x=0) probability for mean: $mean")).toInt() override fun sample(generator: RandomGenerator): Chain = generator.chain { var n = 0 @@ -37,7 +31,9 @@ class SmallMeanPoissonSampler(mean: Double) : Sampler { override fun toString(): String = "Small Mean Poisson deviate" companion object { - fun of(mean: Double): SmallMeanPoissonSampler = - SmallMeanPoissonSampler(mean) + fun of(mean: Double): SmallMeanPoissonSampler { + require(mean > 0) { "mean is not strictly positive: $mean" } + return SmallMeanPoissonSampler(mean) + } } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt index 57e7fc47e..3d22c38a5 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt @@ -7,7 +7,7 @@ import scientifik.kmath.prob.Sampler import scientifik.kmath.prob.chain import kotlin.math.* -class ZigguratNormalizedGaussianSampler() : +class ZigguratNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { private fun sampleOne(generator: RandomGenerator): Double { @@ -63,7 +63,6 @@ class ZigguratNormalizedGaussianSampler() : private val K: LongArray = LongArray(LEN) private val W: DoubleArray = DoubleArray(LEN) private val F: DoubleArray = DoubleArray(LEN) - private fun gauss(x: Double): Double = exp(-0.5 * x * x) init { // Filling the tables. @@ -91,5 +90,8 @@ class ZigguratNormalizedGaussianSampler() : W[i] = d * ONE_OVER_MAX } } + + fun of(): ZigguratNormalizedGaussianSampler = ZigguratNormalizedGaussianSampler() + private fun gauss(x: Double): Double = exp(-0.5 * x * x) } } From 2b24bd979e282d35f3f8e15fd52ef3e5904af97e Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 8 Jun 2020 17:36:14 +0700 Subject: [PATCH 005/393] Add Apache Javadocs references --- .../kmath/prob/samplers/AhrensDieterExponentialSampler.kt | 5 +++++ .../prob/samplers/BoxMullerNormalizedGaussianSampler.kt | 5 +++++ .../scientifik/kmath/prob/samplers/GaussianSampler.kt | 5 +++++ .../kmath/prob/samplers/KempSmallMeanPoissonSampler.kt | 5 +++++ .../kmath/prob/samplers/LargeMeanPoissonSampler.kt | 7 ++++++- .../prob/samplers/MarsagliaNormalizedGaussianSampler.kt | 5 +++++ .../scientifik/kmath/prob/samplers/PoissonSampler.kt | 6 +++++- .../kmath/prob/samplers/SmallMeanPoissonSampler.kt | 5 +++++ .../prob/samplers/ZigguratNormalizedGaussianSampler.kt | 5 +++++ 9 files changed, 46 insertions(+), 2 deletions(-) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt index 794c1010d..a83bf6e12 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt @@ -7,6 +7,11 @@ import scientifik.kmath.prob.chain import kotlin.math.ln import kotlin.math.pow +/** + * Based on commons-rng implementation. + * + * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.html + */ class AhrensDieterExponentialSampler private constructor(val mean: Double) : Sampler { override fun sample(generator: RandomGenerator): Chain = generator.chain { // Step 1: diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt index 57c38d6b7..ef5b36289 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt @@ -6,6 +6,11 @@ import scientifik.kmath.prob.Sampler import scientifik.kmath.prob.chain import kotlin.math.* +/** + * Based on commons-rng implementation. + * + * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.html + */ class BoxMullerNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { private var nextGaussian: Double = Double.NaN diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt index 9af468858..2a6bd6a09 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt @@ -5,6 +5,11 @@ import scientifik.kmath.chains.map import scientifik.kmath.prob.RandomGenerator import scientifik.kmath.prob.Sampler +/** + * Based on commons-rng implementation. + * + * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/GaussianSampler.html + */ class GaussianSampler private constructor( private val mean: Double, private val standardDeviation: Double, diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt index 65e762b68..45afaa179 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt @@ -6,6 +6,11 @@ import scientifik.kmath.prob.Sampler import scientifik.kmath.prob.chain import kotlin.math.exp +/** + * Based on commons-rng implementation. + * + * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.html + */ class KempSmallMeanPoissonSampler private constructor( private val p0: Double, private val mean: Double diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt index 39a3dc168..f14aaa8ab 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt @@ -8,9 +8,14 @@ import scientifik.kmath.prob.Sampler import scientifik.kmath.prob.next import kotlin.math.* +/** + * Based on commons-rng implementation. + * + * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/LargeMeanPoissonSampler.html + */ class LargeMeanPoissonSampler private constructor(val mean: Double) : Sampler { private val exponential: Sampler = AhrensDieterExponentialSampler.of(1.0) - private val gaussian: Sampler = ZigguratNormalizedGaussianSampler() + private val gaussian: Sampler = ZigguratNormalizedGaussianSampler.of() private val factorialLog: InternalUtils.FactorialLog = NO_CACHE_FACTORIAL_LOG private val lambda: Double = floor(mean) private val logLambda: Double = ln(lambda) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt index dd8f82a2c..a0711ec24 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt @@ -7,6 +7,11 @@ import scientifik.kmath.prob.chain import kotlin.math.ln import kotlin.math.sqrt +/** + * Based on commons-rng implementation. + * + * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.html + */ class MarsagliaNormalizedGaussianSampler private constructor(): NormalizedGaussianSampler, Sampler { private var nextGaussian = Double.NaN diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/PoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/PoissonSampler.kt index 7b5dedc5b..3a85e6992 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/PoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/PoissonSampler.kt @@ -4,7 +4,11 @@ import scientifik.kmath.chains.Chain import scientifik.kmath.prob.RandomGenerator import scientifik.kmath.prob.Sampler - +/** + * Based on commons-rng implementation. + * + * https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/PoissonSampler.html + */ class PoissonSampler private constructor( mean: Double ) : Sampler { diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt index 7022b0f3a..966d7db9a 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt @@ -8,6 +8,11 @@ import scientifik.kmath.prob.chain import kotlin.math.ceil import kotlin.math.exp +/** + * Based on commons-rng implementation. + * + * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/SmallMeanPoissonSampler.html + */ class SmallMeanPoissonSampler private constructor(mean: Double) : Sampler { private val p0: Double = exp(-mean) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt index 3d22c38a5..b1680d54a 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt @@ -7,6 +7,11 @@ import scientifik.kmath.prob.Sampler import scientifik.kmath.prob.chain import kotlin.math.* +/** + * Based on commons-rng implementation. + * + * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.html + */ class ZigguratNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { From 5ff76209aac70ab0e17fdcdf7b8f8d24a337d15d Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 8 Jun 2020 17:37:35 +0700 Subject: [PATCH 006/393] Specify type explicitly --- .../kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt index b1680d54a..979209e79 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt @@ -60,7 +60,7 @@ class ZigguratNormalizedGaussianSampler private constructor() : companion object { private const val R: Double = 3.442619855899 private const val ONE_OVER_R: Double = 1 / R - private const val V = 9.91256303526217e-3 + private const val V: Double = 9.91256303526217e-3 private val MAX: Double = 2.0.pow(63.0) private val ONE_OVER_MAX: Double = 1.0 / MAX private const val LEN: Int = 128 From d4226b7e7d7587f6b48bcb3b6624f57e8da5167e Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 8 Jun 2020 17:38:48 +0700 Subject: [PATCH 007/393] Reformat --- .../scientifik/kmath/prob/samplers/GaussianSampler.kt | 5 +++-- .../prob/samplers/MarsagliaNormalizedGaussianSampler.kt | 3 --- .../prob/samplers/ZigguratNormalizedGaussianSampler.kt | 8 ++------ 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt index 2a6bd6a09..755c73df3 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt @@ -15,8 +15,9 @@ class GaussianSampler private constructor( private val standardDeviation: Double, private val normalized: NormalizedGaussianSampler ) : Sampler { - override fun sample(generator: RandomGenerator): Chain = - normalized.sample(generator).map { standardDeviation * it + mean } + override fun sample(generator: RandomGenerator): Chain = normalized + .sample(generator) + .map { standardDeviation * it + mean } override fun toString(): String = "Gaussian deviate [$normalized]" diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt index a0711ec24..80d93055d 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt @@ -30,10 +30,8 @@ class MarsagliaNormalizedGaussianSampler private constructor(): NormalizedGaussi if (r2 < 1 && r2 > 0) { // Pair (x, y) is within unit circle. alpha = sqrt(-2 * ln(r2) / r2) - // Keep second element of the pair for next invocation. nextGaussian = alpha * y - // Return the first element of the generated pair. break } @@ -46,7 +44,6 @@ class MarsagliaNormalizedGaussianSampler private constructor(): NormalizedGaussi // Use the second element of the pair (generated at the // previous invocation). val r = nextGaussian - // Both elements of the pair have been used. nextGaussian = Double.NaN r diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt index 979209e79..de593a811 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt @@ -73,8 +73,7 @@ class ZigguratNormalizedGaussianSampler private constructor() : // Filling the tables. var d = R var t = d - var fd = - gauss(d) + var fd = gauss(d) val q = V / fd K[0] = (d / q * MAX).toLong() K[1] = 0 @@ -85,10 +84,7 @@ class ZigguratNormalizedGaussianSampler private constructor() : (LAST - 1 downTo 1).forEach { i -> d = sqrt(-2 * ln(V / d + fd)) - fd = - gauss( - d - ) + fd = gauss(d) K[i + 1] = (d / t * MAX).toLong() t = d F[i] = fd From 46649a1ddf7e479f9ddedd09585f49dbb6690420 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 8 Jun 2020 18:02:15 +0700 Subject: [PATCH 008/393] Delete unused InternalUtils functions --- .../kmath/prob/samplers/InternalUtils.kt | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalUtils.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalUtils.kt index f2f1b3865..c83f35d32 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalUtils.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalUtils.kt @@ -18,24 +18,6 @@ internal object InternalUtils { fun factorial(n: Int): Long = FACTORIALS[n] - fun validateProbabilities(probabilities: DoubleArray): Double { - require(probabilities.isNotEmpty()) { "Probabilities must not be empty." } - var sumProb = 0.0 - - probabilities.forEach { prob -> - validateProbability(prob) - sumProb += prob - } - - require(!(sumProb.isInfinite() || sumProb <= 0)) { "Invalid sum of probabilities: $sumProb" } - return sumProb - } - - private fun validateProbability(probability: Double): Unit = - require(!(probability < 0 || probability.isInfinite() || probability.isNaN())) { - "Invalid probability: $probability" - } - class FactorialLog private constructor( numValues: Int, cache: DoubleArray? @@ -64,9 +46,6 @@ internal object InternalUtils { } } - fun withCache(cacheSize: Int): FactorialLog = - FactorialLog(cacheSize, logFactorials) - fun value(n: Int): Double { if (n < logFactorials.size) return logFactorials[n] From 246feacd72140597f4a94bcaa920b0afe30a058e Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 8 Jun 2020 18:05:56 +0700 Subject: [PATCH 009/393] Delete unused RandomGenerator-to-URP adapter --- .../kmath/prob/RandomSourceGenerator.kt | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt deleted file mode 100644 index b4056cabc..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt +++ /dev/null @@ -1,29 +0,0 @@ -package scientifik.kmath.prob - -import scientifik.kmath.commons.rng.UniformRandomProvider - - -inline class RandomGeneratorProvider(val generator: RandomGenerator) : - UniformRandomProvider { - override fun nextBoolean(): Boolean = generator.nextBoolean() - - override fun nextFloat(): Float = generator.nextDouble().toFloat() - - override fun nextBytes(bytes: ByteArray) { - generator.fillBytes(bytes) - } - - override fun nextBytes(bytes: ByteArray, start: Int, len: Int) { - generator.fillBytes(bytes, start, start + len) - } - - override fun nextInt(): Int = generator.nextInt() - - override fun nextInt(n: Int): Int = generator.nextInt(n) - - override fun nextDouble(): Double = generator.nextDouble() - - override fun nextLong(): Long = generator.nextLong() - - override fun nextLong(n: Long): Long = generator.nextLong(n) -} From 822f960e9c31bced450088e8f1721fd3a79f83c1 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Mon, 8 Jun 2020 18:19:18 +0700 Subject: [PATCH 010/393] Fix broken demos, add newlines at the end of files --- .../commons/prob/DistributionBenchmark.kt | 44 ++++++++----------- .../kmath/commons/prob/DistributionDemo.kt | 5 +-- .../scientifik/kmath/prob/RandomChain.kt | 2 +- .../scientifik/kmath/prob/RandomGenerator.kt | 2 +- 4 files changed, 22 insertions(+), 31 deletions(-) diff --git a/examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionBenchmark.kt b/examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionBenchmark.kt index b060cddb6..34549710c 100644 --- a/examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionBenchmark.kt @@ -3,25 +3,24 @@ package scientifik.kmath.commons.prob import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking -import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler import org.apache.commons.rng.simple.RandomSource -import scientifik.kmath.chains.BlockingRealChain -import scientifik.kmath.prob.* +import scientifik.kmath.prob.RandomChain +import scientifik.kmath.prob.RandomGenerator +import scientifik.kmath.prob.fromSource import java.time.Duration import java.time.Instant +import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler as ApacheZigguratNormalizedGaussianSampler +import scientifik.kmath.prob.samplers.ZigguratNormalizedGaussianSampler as KMathZigguratNormalizedGaussianSampler - -private suspend fun runChain(): Duration { +private suspend fun runKMathChained(): Duration { val generator = RandomGenerator.fromSource(RandomSource.MT, 123L) - - val normal = Distribution.normal(NormalSamplerMethod.Ziggurat) - val chain = normal.sample(generator) as BlockingRealChain - + val normal = KMathZigguratNormalizedGaussianSampler.of() + val chain = normal.sample(generator) as RandomChain val startTime = Instant.now() var sum = 0.0 - repeat(10000001) { counter -> - sum += chain.nextDouble() + repeat(10000001) { counter -> + sum += chain.next() if (counter % 100000 == 0) { val duration = Duration.between(startTime, Instant.now()) @@ -32,9 +31,9 @@ private suspend fun runChain(): Duration { return Duration.between(startTime, Instant.now()) } -private fun runDirect(): Duration { - val provider = RandomSource.create(RandomSource.MT, 123L) - val sampler = ZigguratNormalizedGaussianSampler(provider) +private fun runApacheDirect(): Duration { + val rng = RandomSource.create(RandomSource.MT, 123L) + val sampler = ApacheZigguratNormalizedGaussianSampler.of(rng) val startTime = Instant.now() var sum = 0.0 @@ -56,16 +55,9 @@ private fun runDirect(): Duration { */ fun main() { runBlocking(Dispatchers.Default) { - val chainJob = async { - runChain() - } - - val directJob = async { - runDirect() - } - - println("Chain: ${chainJob.await()}") - println("Direct: ${directJob.await()}") + val chainJob = async { runKMathChained() } + val directJob = async { runApacheDirect() } + println("KMath Chained: ${chainJob.await()}") + println("Apache Direct: ${directJob.await()}") } - -} \ No newline at end of file +} diff --git a/examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionDemo.kt b/examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionDemo.kt index e059415dc..88fc38e94 100644 --- a/examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionDemo.kt +++ b/examples/src/main/kotlin/scientifik/kmath/commons/prob/DistributionDemo.kt @@ -3,9 +3,8 @@ package scientifik.kmath.commons.prob import kotlinx.coroutines.runBlocking import scientifik.kmath.chains.Chain import scientifik.kmath.chains.collectWithState -import scientifik.kmath.prob.Distribution import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.normal +import scientifik.kmath.prob.samplers.ZigguratNormalizedGaussianSampler data class AveragingChainState(var num: Int = 0, var value: Double = 0.0) @@ -18,7 +17,7 @@ fun Chain.mean(): Chain = collectWithState(AveragingChainState() fun main() { - val normal = Distribution.normal() + val normal = ZigguratNormalizedGaussianSampler.of() val chain = normal.sample(RandomGenerator.default).mean() runBlocking { diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt index 47fc6e4c5..49163c701 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt @@ -11,4 +11,4 @@ class RandomChain(val generator: RandomGenerator, private val gen: suspen override fun fork(): Chain = RandomChain(generator.fork(), gen) } -fun RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain = RandomChain(this, gen) \ No newline at end of file +fun RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain = RandomChain(this, gen) diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt index 4b42db927..6bdabed9d 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt @@ -44,4 +44,4 @@ inline class DefaultGenerator(private val random: Random = Random) : RandomGener override fun nextBytes(size: Int): ByteArray = random.nextBytes(size) override fun fork(): RandomGenerator = RandomGenerator.default(random.nextLong()) -} \ No newline at end of file +} From 46f6d57fd944bc8719c8b99f296f151ca9eb4b85 Mon Sep 17 00:00:00 2001 From: Commander Tvis Date: Fri, 12 Jun 2020 01:13:15 +0700 Subject: [PATCH 011/393] Add 2 more samplers, replace SimpleChain with generator.chain --- .../AhrensDieterMarsagliaTsangGammaSampler.kt | 112 ++++++++ .../samplers/AliasMethodDiscreteSampler.kt | 260 ++++++++++++++++++ .../kmath/prob/samplers/InternalUtils.kt | 30 +- .../prob/samplers/LargeMeanPoissonSampler.kt | 4 +- .../prob/samplers/SmallMeanPoissonSampler.kt | 1 - .../ZigguratNormalizedGaussianSampler.kt | 1 - 6 files changed, 396 insertions(+), 12 deletions(-) create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt create mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AliasMethodDiscreteSampler.kt diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt new file mode 100644 index 000000000..57bc778ba --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt @@ -0,0 +1,112 @@ +package scientifik.kmath.prob.samplers + +import scientifik.kmath.chains.Chain +import scientifik.kmath.prob.RandomGenerator +import scientifik.kmath.prob.Sampler +import scientifik.kmath.prob.chain +import scientifik.kmath.prob.next +import kotlin.math.* + +class AhrensDieterMarsagliaTsangGammaSampler private constructor( + alpha: Double, + theta: Double +) : Sampler { + private val delegate: BaseGammaSampler = + if (alpha < 1) AhrensDieterGammaSampler(alpha, theta) else MarsagliaTsangGammaSampler( + alpha, + theta + ) + + private abstract class BaseGammaSampler internal constructor( + protected val alpha: Double, + protected val theta: Double + ) : Sampler { + init { + require(alpha > 0) { "alpha is not strictly positive: $alpha" } + require(theta > 0) { "theta is not strictly positive: $theta" } + } + + override fun toString(): String = "Ahrens-Dieter-Marsaglia-Tsang Gamma deviate" + } + + private class AhrensDieterGammaSampler internal constructor(alpha: Double, theta: Double) : + BaseGammaSampler(alpha, theta) { + private val oneOverAlpha: Double = 1.0 / alpha + private val bGSOptim: Double = 1.0 + alpha / E + + override fun sample(generator: RandomGenerator): Chain = generator.chain { + var x: Double + + // [1]: p. 228, Algorithm GS. + while (true) { + // Step 1: + val u = generator.nextDouble() + val p = bGSOptim * u + + if (p <= 1) { + // Step 2: + x = p.pow(oneOverAlpha) + val u2 = generator.nextDouble() + + if (u2 > exp(-x)) // Reject. + continue + + break + } + + // Step 3: + x = -ln((bGSOptim - p) * oneOverAlpha) + val u2: Double = generator.nextDouble() + if (u2 <= x.pow(alpha - 1.0)) break + // Reject and continue. + } + + x * theta + } + } + + private class MarsagliaTsangGammaSampler internal constructor(alpha: Double, theta: Double) : + BaseGammaSampler(alpha, theta) { + private val dOptim: Double + private val cOptim: Double + private val gaussian: NormalizedGaussianSampler + + init { + gaussian = ZigguratNormalizedGaussianSampler.of() + dOptim = alpha - ONE_THIRD + cOptim = ONE_THIRD / sqrt(dOptim) + } + + override fun sample(generator: RandomGenerator): Chain = generator.chain { + var v: Double + + while (true) { + val x = gaussian.next(generator) + val oPcTx = 1 + cOptim * x + v = oPcTx * oPcTx * oPcTx + if (v <= 0) continue + val x2 = x * x + val u = generator.nextDouble() + // Squeeze. + if (u < 1 - 0.0331 * x2 * x2) break + if (ln(u) < 0.5 * x2 + dOptim * (1 - v + ln(v))) break + } + + theta * dOptim * v + } + + companion object { + private const val ONE_THIRD = 1.0 / 3.0 + } + } + + override fun sample(generator: RandomGenerator): Chain = delegate.sample(generator) + override fun toString(): String = delegate.toString() + + companion object { + fun of( + alpha: Double, + theta: Double + ): Sampler = AhrensDieterMarsagliaTsangGammaSampler(alpha, theta) + } +} \ No newline at end of file diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AliasMethodDiscreteSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AliasMethodDiscreteSampler.kt new file mode 100644 index 000000000..6b514a40b --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AliasMethodDiscreteSampler.kt @@ -0,0 +1,260 @@ +package scientifik.kmath.prob.samplers + +import scientifik.kmath.chains.Chain +import scientifik.kmath.prob.RandomGenerator +import scientifik.kmath.prob.Sampler +import scientifik.kmath.prob.chain +import kotlin.jvm.JvmOverloads +import kotlin.math.ceil +import kotlin.math.max +import kotlin.math.min + +open class AliasMethodDiscreteSampler private constructor( + // Deliberate direct storage of input arrays + protected val probability: LongArray, + protected val alias: IntArray +) : Sampler { + + private class SmallTableAliasMethodDiscreteSampler internal constructor( + probability: LongArray, + alias: IntArray + ) : AliasMethodDiscreteSampler(probability, alias) { + // Assume the table size is a power of 2 and create the mask + private val mask: Int = alias.size - 1 + + override fun sample(generator: RandomGenerator): Chain = generator.chain { + val bits = generator.nextInt() + // Isolate lower bits + val j = bits and mask + + // Optimisation for zero-padded input tables + if (j >= probability.size) + // No probability must use the alias + return@chain alias[j] + + // Create a uniform random deviate as a long. + // This replicates functionality from the o.a.c.rng.core.utils.NumberFactory.makeLong + val longBits = generator.nextInt().toLong() shl 32 or (bits.toLong() and hex_ffffffff) + // Choose between the two. Use a 53-bit long for the probability. + if (longBits ushr 11 < probability[j]) j else alias[j] + } + + private companion object { + private const val hex_ffffffff = 4294967295L + } + } + + override fun sample(generator: RandomGenerator): Chain = generator.chain { + // This implements the algorithm as per Vose (1991): + // v = uniform() in [0, 1) + // j = uniform(n) in [0, n) + // if v < prob[j] then + // return j + // else + // return alias[j] + val j = generator.nextInt(alias.size) + + // Optimisation for zero-padded input tables + // No probability must use the alias + if (j >= probability.size) return@chain alias[j] + + // Note: We could check the probability before computing a deviate. + // p(j) == 0 => alias[j] + // p(j) == 1 => j + // However it is assumed these edge cases are rare: + // + // The probability table will be 1 for approximately 1/n samples, i.e. only the + // last unpaired probability. This is only worth checking for when the table size (n) + // is small. But in that case the user should zero-pad the table for performance. + // + // The probability table will be 0 when an input probability was zero. We + // will assume this is also rare if modelling a discrete distribution where + // all samples are possible. The edge case for zero-padded tables is handled above. + + // Choose between the two. Use a 53-bit long for the probability. + if (generator.nextLong() ushr 11 < probability[j]) j else alias[j] + } + + override fun toString(): String = "Alias method" + + companion object { + private const val DEFAULT_ALPHA = 0 + private const val ZERO = 0.0 + private const val ONE_AS_NUMERATOR = 1L shl 53 + private const val CONVERT_TO_NUMERATOR: Double = ONE_AS_NUMERATOR.toDouble() + private const val MAX_SMALL_POWER_2_SIZE = 1 shl 11 + + @JvmOverloads + fun of( + probabilities: DoubleArray, + alpha: Int = DEFAULT_ALPHA + ): Sampler { + // The Alias method balances N categories with counts around the mean into N sections, + // each allocated 'mean' observations. + // + // Consider 4 categories with counts 6,3,2,1. The histogram can be balanced into a + // 2D array as 4 sections with a height of the mean: + // + // 6 + // 6 + // 6 + // 63 => 6366 -- + // 632 6326 |-- mean + // 6321 6321 -- + // + // section abcd + // + // Each section is divided as: + // a: 6=1/1 + // b: 3=1/1 + // c: 2=2/3; 6=1/3 (6 is the alias) + // d: 1=1/3; 6=2/3 (6 is the alias) + // + // The sample is obtained by randomly selecting a section, then choosing which category + // from the pair based on a uniform random deviate. + val sumProb = InternalUtils.validateProbabilities(probabilities) + // Allow zero-padding + val n = computeSize(probabilities.size, alpha) + // Partition into small and large by splitting on the average. + val mean = sumProb / n + // The cardinality of smallSize + largeSize = n. + // So fill the same array from either end. + val indices = IntArray(n) + var large = n + var small = 0 + + probabilities.indices.forEach { i -> + if (probabilities[i] >= mean) indices[--large] = i else indices[small++] = i + } + + small = fillRemainingIndices(probabilities.size, indices, small) + // This may be smaller than the input length if the probabilities were already padded. + val nonZeroIndex = findLastNonZeroIndex(probabilities) + // The probabilities are modified so use a copy. + // Note: probabilities are required only up to last nonZeroIndex + val remainingProbabilities = probabilities.copyOf(nonZeroIndex + 1) + // Allocate the final tables. + // Probability table may be truncated (when zero padded). + // The alias table is full length. + val probability = LongArray(remainingProbabilities.size) + val alias = IntArray(n) + + // This loop uses each large in turn to fill the alias table for small probabilities that + // do not reach the requirement to fill an entire section alone (i.e. p < mean). + // Since the sum of the small should be less than the sum of the large it should use up + // all the small first. However floating point round-off can result in + // misclassification of items as small or large. The Vose algorithm handles this using + // a while loop conditioned on the size of both sets and a subsequent loop to use + // unpaired items. + while (large != n && small != 0) { + // Index of the small and the large probabilities. + val j = indices[--small] + val k = indices[large++] + + // Optimisation for zero-padded input: + // p(j) = 0 above the last nonZeroIndex + if (j > nonZeroIndex) + // The entire amount for the section is taken from the alias. + remainingProbabilities[k] -= mean + else { + val pj = remainingProbabilities[j] + // Item j is a small probability that is below the mean. + // Compute the weight of the section for item j: pj / mean. + // This is scaled by 2^53 and the ceiling function used to round-up + // the probability to a numerator of a fraction in the range [1,2^53]. + // Ceiling ensures non-zero values. + probability[j] = ceil(CONVERT_TO_NUMERATOR * (pj / mean)).toLong() + // The remaining amount for the section is taken from the alias. + // Effectively: probabilities[k] -= (mean - pj) + remainingProbabilities[k] += pj - mean + } + + // If not j then the alias is k + alias[j] = k + + // Add the remaining probability from large to the appropriate list. + if (remainingProbabilities[k] >= mean) indices[--large] = k else indices[small++] = k + } + + // Final loop conditions to consume unpaired items. + // Note: The large set should never be non-empty but this can occur due to round-off + // error so consume from both. + fillTable(probability, alias, indices, 0, small) + fillTable(probability, alias, indices, large, n) + + // Change the algorithm for small power of 2 sized tables + return if (isSmallPowerOf2(n)) + SmallTableAliasMethodDiscreteSampler(probability, alias) + else + AliasMethodDiscreteSampler(probability, alias) + } + + private fun fillRemainingIndices(length: Int, indices: IntArray, small: Int): Int { + var updatedSmall = small + (length until indices.size).forEach { i -> indices[updatedSmall++] = i } + return updatedSmall + } + + private fun findLastNonZeroIndex(probabilities: DoubleArray): Int { + // No bounds check is performed when decrementing as the array contains at least one + // value above zero. + var nonZeroIndex = probabilities.size - 1 + while (probabilities[nonZeroIndex] == ZERO) nonZeroIndex-- + return nonZeroIndex + } + + private fun computeSize(length: Int, alpha: Int): Int { + // If No padding + if (alpha < 0) return length + // Use the number of leading zeros function to find the next power of 2, + // i.e. ceil(log2(x)) + var pow2 = 32 - numberOfLeadingZeros(length - 1) + // Increase by the alpha. Clip this to limit to a positive integer (2^30) + pow2 = min(30, pow2 + alpha) + // Use max to handle a length above the highest possible power of 2 + return max(length, 1 shl pow2) + } + + private fun fillTable( + probability: LongArray, + alias: IntArray, + indices: IntArray, + start: Int, + end: Int + ) = (start until end).forEach { i -> + val index = indices[i] + probability[index] = ONE_AS_NUMERATOR + alias[index] = index + } + + private fun isSmallPowerOf2(n: Int): Boolean = n <= MAX_SMALL_POWER_2_SIZE && n and n - 1 == 0 + + private fun numberOfLeadingZeros(i: Int): Int { + var mutI = i + if (mutI <= 0) return if (mutI == 0) 32 else 0 + var n = 31 + + if (mutI >= 1 shl 16) { + n -= 16 + mutI = mutI ushr 16 + } + + if (mutI >= 1 shl 8) { + n -= 8 + mutI = mutI ushr 8 + } + + if (mutI >= 1 shl 4) { + n -= 4 + mutI = mutI ushr 4 + } + + if (mutI >= 1 shl 2) { + n -= 2 + mutI = mutI ushr 2 + } + + return n - (mutI ushr 1) + } + } +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalUtils.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalUtils.kt index c83f35d32..611c4064d 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalUtils.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/InternalUtils.kt @@ -18,6 +18,22 @@ internal object InternalUtils { fun factorial(n: Int): Long = FACTORIALS[n] + fun validateProbabilities(probabilities: DoubleArray?): Double { + require(!(probabilities == null || probabilities.isEmpty())) { "Probabilities must not be empty." } + var sumProb = 0.0 + + probabilities.forEach { prob -> + validateProbability(prob) + sumProb += prob + } + + require(!(sumProb.isInfinite() || sumProb <= 0)) { "Invalid sum of probabilities: $sumProb" } + return sumProb + } + + private fun validateProbability(probability: Double): Unit = + require(!(probability < 0 || probability.isInfinite() || probability.isNaN())) { "Invalid probability: $probability" } + class FactorialLog private constructor( numValues: Int, cache: DoubleArray? @@ -30,9 +46,11 @@ internal object InternalUtils { if (cache != null && cache.size > BEGIN_LOG_FACTORIALS) { // Copy available values. endCopy = min(cache.size, numValues) - cache.copyInto(logFactorials, + cache.copyInto( + logFactorials, BEGIN_LOG_FACTORIALS, - BEGIN_LOG_FACTORIALS, endCopy) + BEGIN_LOG_FACTORIALS, endCopy + ) } // All values to be computed else endCopy = BEGIN_LOG_FACTORIALS @@ -50,15 +68,11 @@ internal object InternalUtils { if (n < logFactorials.size) return logFactorials[n] - return if (n < FACTORIALS.size) ln( - FACTORIALS[n].toDouble()) else InternalGamma.logGamma( - n + 1.0 - ) + return if (n < FACTORIALS.size) ln(FACTORIALS[n].toDouble()) else InternalGamma.logGamma(n + 1.0) } companion object { - fun create(): FactorialLog = - FactorialLog(0, null) + fun create(): FactorialLog = FactorialLog(0, null) } } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt index f14aaa8ab..47e84327a 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt @@ -2,9 +2,9 @@ package scientifik.kmath.prob.samplers import scientifik.kmath.chains.Chain import scientifik.kmath.chains.ConstantChain -import scientifik.kmath.chains.SimpleChain import scientifik.kmath.prob.RandomGenerator import scientifik.kmath.prob.Sampler +import scientifik.kmath.prob.chain import scientifik.kmath.prob.next import kotlin.math.* @@ -35,7 +35,7 @@ class LargeMeanPoissonSampler private constructor(val mean: Double) : Sampler = SimpleChain { + override fun sample(generator: RandomGenerator): Chain = generator.chain { // This will never be null. It may be a no-op delegate that returns zero. val y2 = smallMeanPoissonSampler.next(generator) var x: Double diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt index 966d7db9a..dd1a419c9 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt @@ -1,7 +1,6 @@ package scientifik.kmath.prob.samplers import scientifik.kmath.chains.Chain -import scientifik.kmath.chains.SimpleChain import scientifik.kmath.prob.RandomGenerator import scientifik.kmath.prob.Sampler import scientifik.kmath.prob.chain diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt index de593a811..a7956deee 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt @@ -1,7 +1,6 @@ package scientifik.kmath.prob.samplers import scientifik.kmath.chains.Chain -import scientifik.kmath.chains.SimpleChain import scientifik.kmath.prob.RandomGenerator import scientifik.kmath.prob.Sampler import scientifik.kmath.prob.chain From a03c82f758d58aac4f001cae2dcc4cc83ef716c4 Mon Sep 17 00:00:00 2001 From: Iaroslav Date: Fri, 12 Jun 2020 02:49:06 +0700 Subject: [PATCH 012/393] Simplify BlockingIntChain and BlockingRealChain; add blocking extension function for RandomChain; copy general documentation to samplers created with Apache Commons RNG --- .../kmath/chains/BlockingIntChain.kt | 8 ++---- .../kmath/chains/BlockingRealChain.kt | 8 ++---- .../scientifik/kmath/prob/RandomChain.kt | 16 +++++++++++ .../AhrensDieterExponentialSampler.kt | 3 ++- .../AhrensDieterMarsagliaTsangGammaSampler.kt | 10 +++++++ .../samplers/AliasMethodDiscreteSampler.kt | 27 +++++++++++++++++++ .../BoxMullerNormalizedGaussianSampler.kt | 4 ++- .../kmath/prob/samplers/GaussianSampler.kt | 3 ++- .../samplers/KempSmallMeanPoissonSampler.kt | 9 ++++++- .../prob/samplers/LargeMeanPoissonSampler.kt | 10 +++++-- .../MarsagliaNormalizedGaussianSampler.kt | 7 +++-- .../samplers/NormalizedGaussianSampler.kt | 4 +++ .../kmath/prob/samplers/PoissonSampler.kt | 11 ++++++-- .../prob/samplers/SmallMeanPoissonSampler.kt | 9 ++++++- .../ZigguratNormalizedGaussianSampler.kt | 5 +++- 15 files changed, 110 insertions(+), 24 deletions(-) diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt index 6ec84d5c7..ec1633fb0 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt @@ -4,9 +4,5 @@ package scientifik.kmath.chains * Performance optimized chain for integer values */ abstract class BlockingIntChain : Chain { - abstract fun nextInt(): Int - - override suspend fun next(): Int = nextInt() - - fun nextBlock(size: Int): IntArray = IntArray(size) { nextInt() } -} \ No newline at end of file + suspend fun nextBlock(size: Int): IntArray = IntArray(size) { next() } +} diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt index 6b69d2734..f8930815c 100644 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt @@ -4,9 +4,5 @@ package scientifik.kmath.chains * Performance optimized chain for real values */ abstract class BlockingRealChain : Chain { - abstract fun nextDouble(): Double - - override suspend fun next(): Double = nextDouble() - - fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { nextDouble() } -} \ No newline at end of file + suspend fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { next() } +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt index 49163c701..68602e1ea 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt @@ -1,5 +1,7 @@ package scientifik.kmath.prob +import scientifik.kmath.chains.BlockingIntChain +import scientifik.kmath.chains.BlockingRealChain import scientifik.kmath.chains.Chain /** @@ -12,3 +14,17 @@ class RandomChain(val generator: RandomGenerator, private val gen: suspen } fun RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain = RandomChain(this, gen) + +fun RandomChain.blocking(): BlockingRealChain = let { + object : BlockingRealChain() { + override suspend fun next(): Double = it.next() + override fun fork(): Chain = it.fork() + } +} + +fun RandomChain.blocking(): BlockingIntChain = let { + object : BlockingIntChain() { + override suspend fun next(): Int = it.next() + override fun fork(): Chain = it.fork() + } +} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt index a83bf6e12..fa49f194e 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterExponentialSampler.kt @@ -8,8 +8,9 @@ import kotlin.math.ln import kotlin.math.pow /** - * Based on commons-rng implementation. + * Sampling from an [exponential distribution](http://mathworld.wolfram.com/ExponentialDistribution.html). * + * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.html */ class AhrensDieterExponentialSampler private constructor(val mean: Double) : Sampler { diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt index 57bc778ba..f1e622a27 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt @@ -7,6 +7,16 @@ import scientifik.kmath.prob.chain import scientifik.kmath.prob.next import kotlin.math.* +/** + * Sampling from the [gamma distribution](http://mathworld.wolfram.com/GammaDistribution.html). + * - For 0 < alpha < 1: + * Ahrens, J. H. and Dieter, U., Computer methods for sampling from gamma, beta, Poisson and binomial distributions, Computing, 12, 223-246, 1974. + * - For alpha >= 1: + * Marsaglia and Tsang, A Simple Method for Generating Gamma Variables. ACM Transactions on Mathematical Software, Volume 26 Issue 3, September, 2000. + * + * Based on Commons RNG implementation. + * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterMarsagliaTsangGammaSampler.html + */ class AhrensDieterMarsagliaTsangGammaSampler private constructor( alpha: Double, theta: Double diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AliasMethodDiscreteSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AliasMethodDiscreteSampler.kt index 6b514a40b..5af6986ea 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AliasMethodDiscreteSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/AliasMethodDiscreteSampler.kt @@ -9,6 +9,33 @@ import kotlin.math.ceil import kotlin.math.max import kotlin.math.min +/** + * Distribution sampler that uses the Alias method. It can be used to sample from n values each with an associated + * probability. This implementation is based on the detailed explanation of the alias method by Keith Schartz and + * implements Vose's algorithm. + * + * Vose, M.D., A linear algorithm for generating random numbers with a given distribution, IEEE Transactions on + * Software Engineering, 17, 972-975, 1991. he algorithm will sample values in O(1) time after a pre-processing step + * of O(n) time. + * + * The alias tables are constructed using fraction probabilities with an assumed denominator of 253. In the generic + * case sampling uses UniformRandomProvider.nextInt(int) and the upper 53-bits from UniformRandomProvider.nextLong(). + * + * Zero padding the input probabilities can be used to make more sampling more efficient. Any zero entry will always be + * aliased removing the requirement to compute a long. Increased sampling speed comes at the cost of increased storage + * space. The algorithm requires approximately 12 bytes of storage per input probability, that is n * 12 for size n. + * Zero-padding only requires 4 bytes of storage per padded value as the probability is known to be zero. + * + * An optimisation is performed for small table sizes that are a power of 2. In this case the sampling uses 1 or 2 + * calls from UniformRandomProvider.nextInt() to generate up to 64-bits for creation of an 11-bit index and 53-bits + * for the long. This optimisation requires a generator with a high cycle length for the lower order bits. + * + * Larger table sizes that are a power of 2 will benefit from fast algorithms for UniformRandomProvider.nextInt(int) + * that exploit the power of 2. + * + * Based on Commons RNG implementation. + * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AliasMethodDiscreteSampler.html + */ open class AliasMethodDiscreteSampler private constructor( // Deliberate direct storage of input arrays protected val probability: LongArray, diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt index ef5b36289..a2d10e9f1 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt @@ -7,8 +7,10 @@ import scientifik.kmath.prob.chain import kotlin.math.* /** - * Based on commons-rng implementation. + * [Box-Muller algorithm](https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform) for sampling from a Gaussian + * distribution. * + * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.html */ class BoxMullerNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt index 755c73df3..2516f0480 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/GaussianSampler.kt @@ -6,8 +6,9 @@ import scientifik.kmath.prob.RandomGenerator import scientifik.kmath.prob.Sampler /** - * Based on commons-rng implementation. + * Sampling from a Gaussian distribution with given mean and standard deviation. * + * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/GaussianSampler.html */ class GaussianSampler private constructor( diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt index 45afaa179..bb1dfa0c2 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt @@ -7,8 +7,15 @@ import scientifik.kmath.prob.chain import kotlin.math.exp /** - * Based on commons-rng implementation. + * Sampler for the Poisson distribution. + * - Kemp, A, W, (1981) Efficient Generation of Logarithmically Distributed Pseudo-Random Variables. Journal of the Royal Statistical Society. Vol. 30, No. 3, pp. 249-253. + * This sampler is suitable for mean < 40. For large means, LargeMeanPoissonSampler should be used instead. * + * Note: The algorithm uses a recurrence relation to compute the Poisson probability and a rolling summation for the cumulative probability. When the mean is large the initial probability (Math.exp(-mean)) is zero and an exception is raised by the constructor. + * + * Sampling uses 1 call to UniformRandomProvider.nextDouble(). This method provides an alternative to the SmallMeanPoissonSampler for slow generators of double. + * + * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.html */ class KempSmallMeanPoissonSampler private constructor( diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt index 47e84327a..eafe28b39 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/LargeMeanPoissonSampler.kt @@ -9,8 +9,14 @@ import scientifik.kmath.prob.next import kotlin.math.* /** - * Based on commons-rng implementation. + * Sampler for the Poisson distribution. + * - For large means, we use the rejection algorithm described in + * Devroye, Luc. (1981).The Computer Generation of Poisson Random Variables + * Computing vol. 26 pp. 197-207. * + * This sampler is suitable for mean >= 40. + * + * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/LargeMeanPoissonSampler.html */ class LargeMeanPoissonSampler private constructor(val mean: Double) : Sampler { @@ -112,7 +118,7 @@ class LargeMeanPoissonSampler private constructor(val mean: Double) : Sampler { + private val NO_SMALL_MEAN_POISSON_SAMPLER: Sampler = object : Sampler { override fun sample(generator: RandomGenerator): Chain = ConstantChain(0) } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt index 80d93055d..eec791906 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt @@ -8,11 +8,14 @@ import kotlin.math.ln import kotlin.math.sqrt /** - * Based on commons-rng implementation. + * [Marsaglia polar method](https://en.wikipedia.org/wiki/Marsaglia_polar_method) for sampling from a Gaussian + * distribution with mean 0 and standard deviation 1. This is a variation of the algorithm implemented in + * [BoxMullerNormalizedGaussianSampler]. * + * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.html */ -class MarsagliaNormalizedGaussianSampler private constructor(): NormalizedGaussianSampler, Sampler { +class MarsagliaNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { private var nextGaussian = Double.NaN override fun sample(generator: RandomGenerator): Chain = generator.chain { diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/NormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/NormalizedGaussianSampler.kt index 0e5d6db59..0ead77b5a 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/NormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/NormalizedGaussianSampler.kt @@ -2,4 +2,8 @@ package scientifik.kmath.prob.samplers import scientifik.kmath.prob.Sampler +/** + * Marker interface for a sampler that generates values from an N(0,1) + * [Gaussian distribution](https://en.wikipedia.org/wiki/Normal_distribution). + */ interface NormalizedGaussianSampler : Sampler diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/PoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/PoissonSampler.kt index 3a85e6992..4648940e1 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/PoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/PoissonSampler.kt @@ -5,9 +5,16 @@ import scientifik.kmath.prob.RandomGenerator import scientifik.kmath.prob.Sampler /** - * Based on commons-rng implementation. + * Sampler for the Poisson distribution. + * - For small means, a Poisson process is simulated using uniform deviates, as described in + * Knuth (1969). Seminumerical Algorithms. The Art of Computer Programming, Volume 2. Chapter 3.4.1.F.3 + * Important integer-valued distributions: The Poisson distribution. Addison Wesley. + * The Poisson process (and hence, the returned value) is bounded by 1000 * mean. + * - For large means, we use the rejection algorithm described in + * Devroye, Luc. (1981). The Computer Generation of Poisson Random Variables Computing vol. 26 pp. 197-207. * - * https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/PoissonSampler.html + * Based on Commons RNG implementation. + * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/PoissonSampler.html */ class PoissonSampler private constructor( mean: Double diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt index dd1a419c9..f5b0eef68 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/SmallMeanPoissonSampler.kt @@ -8,7 +8,14 @@ import kotlin.math.ceil import kotlin.math.exp /** - * Based on commons-rng implementation. + * Sampler for the Poisson distribution. + * - For small means, a Poisson process is simulated using uniform deviates, as described in + * Knuth (1969). Seminumerical Algorithms. The Art of Computer Programming, Volume 2. Chapter 3.4.1.F.3 Important + * integer-valued distributions: The Poisson distribution. Addison Wesley. + * - The Poisson process (and hence, the returned value) is bounded by 1000 * mean. + * This sampler is suitable for mean < 40. For large means, [LargeMeanPoissonSampler] should be used instead. + * + * Based on Commons RNG implementation. * * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/SmallMeanPoissonSampler.html */ diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt index a7956deee..421555d64 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt @@ -7,8 +7,11 @@ import scientifik.kmath.prob.chain import kotlin.math.* /** - * Based on commons-rng implementation. + * [Marsaglia and Tsang "Ziggurat"](https://en.wikipedia.org/wiki/Ziggurat_algorithm) method for sampling from a + * Gaussian distribution with mean 0 and standard deviation 1. The algorithm is explained in this paper and this + * implementation has been adapted from the C code provided therein. * + * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.html */ class ZigguratNormalizedGaussianSampler private constructor() : From 53ebec2e01bd7d0bfe1eda758bec01e92af2ebb7 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 27 Sep 2020 15:16:12 +0700 Subject: [PATCH 013/393] Perform 1.4 and explicit API migrations, refactor blocking chain, make tests work --- .../kscience/kmath/chains/BlockingIntChain.kt | 9 ++-- .../kmath/chains/BlockingRealChain.kt | 9 ++-- .../kmath/chains/BlockingIntChain.kt | 8 ---- .../kmath/chains/BlockingRealChain.kt | 8 ---- .../kscience/kmath/prob/Distribution.kt | 3 +- .../kmath/prob/FactorizedDistribution.kt | 2 +- .../kotlin/kscience/kmath/prob/RandomChain.kt | 7 ++- .../AhrensDieterExponentialSampler.kt | 18 +++---- .../AhrensDieterMarsagliaTsangGammaSampler.kt | 31 ++++++------ .../samplers/AliasMethodDiscreteSampler.kt | 20 ++++---- .../BoxMullerNormalizedGaussianSampler.kt | 20 ++++---- .../kmath/prob/samplers/GaussianSampler.kt | 22 ++++----- .../kmath/prob/samplers/InternalGamma.kt | 2 +- .../kmath/prob/samplers/InternalUtils.kt | 2 +- .../samplers/KempSmallMeanPoissonSampler.kt | 20 ++++---- .../prob/samplers/LargeMeanPoissonSampler.kt | 22 ++++----- .../MarsagliaNormalizedGaussianSampler.kt | 20 ++++---- .../samplers/NormalizedGaussianSampler.kt | 6 +-- .../kmath/prob/samplers/PoissonSampler.kt | 20 ++++---- .../prob/samplers/SmallMeanPoissonSampler.kt | 20 ++++---- .../ZigguratNormalizedGaussianSampler.kt | 21 ++++----- .../kmath/prob/FactorizedDistribution.kt | 46 ------------------ .../scientifik/kmath/prob/RandomChain.kt | 30 ------------ .../scientifik/kmath/prob/RandomGenerator.kt | 47 ------------------- .../kmath/prob/RandomSourceGenerator.kt | 21 +++++---- .../kmath/prob/CommonsDistributionsTest.kt | 11 ++--- 26 files changed, 149 insertions(+), 296 deletions(-) delete mode 100644 kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt delete mode 100644 kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt diff --git a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingIntChain.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingIntChain.kt index 6088267a2..766311fc3 100644 --- a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingIntChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingIntChain.kt @@ -3,10 +3,7 @@ package kscience.kmath.chains /** * Performance optimized chain for integer values */ -public abstract class BlockingIntChain : Chain { - public abstract fun nextInt(): Int - - override suspend fun next(): Int = nextInt() - - public fun nextBlock(size: Int): IntArray = IntArray(size) { nextInt() } +public interface BlockingIntChain : Chain { + public override suspend fun next(): Int + public suspend fun nextBlock(size: Int): IntArray = IntArray(size) { next() } } diff --git a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingRealChain.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingRealChain.kt index 718b3a18b..7c463b109 100644 --- a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingRealChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingRealChain.kt @@ -3,10 +3,7 @@ package kscience.kmath.chains /** * Performance optimized chain for real values */ -public abstract class BlockingRealChain : Chain { - public abstract fun nextDouble(): Double - - override suspend fun next(): Double = nextDouble() - - public fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { nextDouble() } +public interface BlockingRealChain : Chain { + public override suspend fun next(): Double + public suspend fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { next() } } diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt deleted file mode 100644 index ec1633fb0..000000000 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingIntChain.kt +++ /dev/null @@ -1,8 +0,0 @@ -package scientifik.kmath.chains - -/** - * Performance optimized chain for integer values - */ -abstract class BlockingIntChain : Chain { - suspend fun nextBlock(size: Int): IntArray = IntArray(size) { next() } -} diff --git a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt b/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt deleted file mode 100644 index f8930815c..000000000 --- a/kmath-coroutines/src/commonMain/kotlin/scientifik/kmath/chains/BlockingRealChain.kt +++ /dev/null @@ -1,8 +0,0 @@ -package scientifik.kmath.chains - -/** - * Performance optimized chain for real values - */ -abstract class BlockingRealChain : Chain { - suspend fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { next() } -} diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt index 8ca28aedb..b3f1524ea 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt @@ -1,5 +1,6 @@ package kscience.kmath.prob +import kotlinx.coroutines.flow.first import kscience.kmath.chains.Chain import kscience.kmath.chains.collect import kscience.kmath.structures.Buffer @@ -70,7 +71,7 @@ public fun Sampler.sampleBuffer( } } -suspend fun Sampler.next(generator: RandomGenerator) = sample(generator).first() +public suspend fun Sampler.next(generator: RandomGenerator): T = sample(generator).first() /** * Generate a bunch of samples from real distributions diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt index 4d713fc4e..128b284be 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt @@ -14,7 +14,7 @@ public interface NamedDistribution : Distribution> public class FactorizedDistribution(public val distributions: Collection>) : NamedDistribution { override fun probability(arg: Map): Double = - distributions.fold(1.0) { acc, distr -> acc * distr.probability(arg) } + distributions.fold(1.0) { acc, dist -> acc * dist.probability(arg) } override fun sample(generator: RandomGenerator): Chain> { val chains = distributions.map { it.sample(generator) } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomChain.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomChain.kt index b4a80f6c5..70fa8b97b 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomChain.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomChain.kt @@ -1,17 +1,22 @@ package kscience.kmath.prob +import kscience.kmath.chains.BlockingIntChain +import kscience.kmath.chains.BlockingRealChain import kscience.kmath.chains.Chain /** * A possibly stateful chain producing random values. + * + * @property generator the underlying [RandomGenerator] instance. */ public class RandomChain( public val generator: RandomGenerator, private val gen: suspend RandomGenerator.() -> R ) : Chain { override suspend fun next(): R = generator.gen() - override fun fork(): Chain = RandomChain(generator.fork(), gen) } public fun RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain = RandomChain(this, gen) +public fun Chain.blocking(): BlockingRealChain = object : Chain by this, BlockingRealChain {} +public fun Chain.blocking(): BlockingIntChain = object : Chain by this, BlockingIntChain {} diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AhrensDieterExponentialSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AhrensDieterExponentialSampler.kt index fa49f194e..dc388a3ea 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AhrensDieterExponentialSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AhrensDieterExponentialSampler.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers -import scientifik.kmath.chains.Chain -import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.Sampler -import scientifik.kmath.prob.chain +import kscience.kmath.chains.Chain +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.Sampler +import kscience.kmath.prob.chain import kotlin.math.ln import kotlin.math.pow @@ -13,8 +13,8 @@ import kotlin.math.pow * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.html */ -class AhrensDieterExponentialSampler private constructor(val mean: Double) : Sampler { - override fun sample(generator: RandomGenerator): Chain = generator.chain { +public class AhrensDieterExponentialSampler private constructor(public val mean: Double) : Sampler { + public override fun sample(generator: RandomGenerator): Chain = generator.chain { // Step 1: var a = 0.0 var u = nextDouble() @@ -47,7 +47,7 @@ class AhrensDieterExponentialSampler private constructor(val mean: Double) : Sam override fun toString(): String = "Ahrens-Dieter Exponential deviate" - companion object { + public companion object { private val EXPONENTIAL_SA_QI by lazy { DoubleArray(16) } init { @@ -64,7 +64,7 @@ class AhrensDieterExponentialSampler private constructor(val mean: Double) : Sam } } - fun of(mean: Double): AhrensDieterExponentialSampler { + public fun of(mean: Double): AhrensDieterExponentialSampler { require(mean > 0) { "mean is not strictly positive: $mean" } return AhrensDieterExponentialSampler(mean) } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt index f1e622a27..e18a44cb9 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt @@ -1,10 +1,10 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers -import scientifik.kmath.chains.Chain -import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.Sampler -import scientifik.kmath.prob.chain -import scientifik.kmath.prob.next +import kscience.kmath.chains.Chain +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.Sampler +import kscience.kmath.prob.chain +import kscience.kmath.prob.next import kotlin.math.* /** @@ -17,15 +17,12 @@ import kotlin.math.* * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterMarsagliaTsangGammaSampler.html */ -class AhrensDieterMarsagliaTsangGammaSampler private constructor( +public class AhrensDieterMarsagliaTsangGammaSampler private constructor( alpha: Double, theta: Double ) : Sampler { private val delegate: BaseGammaSampler = - if (alpha < 1) AhrensDieterGammaSampler(alpha, theta) else MarsagliaTsangGammaSampler( - alpha, - theta - ) + if (alpha < 1) AhrensDieterGammaSampler(alpha, theta) else MarsagliaTsangGammaSampler(alpha, theta) private abstract class BaseGammaSampler internal constructor( protected val alpha: Double, @@ -39,7 +36,7 @@ class AhrensDieterMarsagliaTsangGammaSampler private constructor( override fun toString(): String = "Ahrens-Dieter-Marsaglia-Tsang Gamma deviate" } - private class AhrensDieterGammaSampler internal constructor(alpha: Double, theta: Double) : + private class AhrensDieterGammaSampler(alpha: Double, theta: Double) : BaseGammaSampler(alpha, theta) { private val oneOverAlpha: Double = 1.0 / alpha private val bGSOptim: Double = 1.0 + alpha / E @@ -75,7 +72,7 @@ class AhrensDieterMarsagliaTsangGammaSampler private constructor( } } - private class MarsagliaTsangGammaSampler internal constructor(alpha: Double, theta: Double) : + private class MarsagliaTsangGammaSampler(alpha: Double, theta: Double) : BaseGammaSampler(alpha, theta) { private val dOptim: Double private val cOptim: Double @@ -110,11 +107,11 @@ class AhrensDieterMarsagliaTsangGammaSampler private constructor( } } - override fun sample(generator: RandomGenerator): Chain = delegate.sample(generator) - override fun toString(): String = delegate.toString() + public override fun sample(generator: RandomGenerator): Chain = delegate.sample(generator) + public override fun toString(): String = delegate.toString() - companion object { - fun of( + public companion object { + public fun of( alpha: Double, theta: Double ): Sampler = AhrensDieterMarsagliaTsangGammaSampler(alpha, theta) diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AliasMethodDiscreteSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AliasMethodDiscreteSampler.kt index 5af6986ea..c5eed2990 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AliasMethodDiscreteSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AliasMethodDiscreteSampler.kt @@ -1,10 +1,9 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers -import scientifik.kmath.chains.Chain -import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.Sampler -import scientifik.kmath.prob.chain -import kotlin.jvm.JvmOverloads +import kscience.kmath.chains.Chain +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.Sampler +import kscience.kmath.prob.chain import kotlin.math.ceil import kotlin.math.max import kotlin.math.min @@ -36,7 +35,7 @@ import kotlin.math.min * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AliasMethodDiscreteSampler.html */ -open class AliasMethodDiscreteSampler private constructor( +public open class AliasMethodDiscreteSampler private constructor( // Deliberate direct storage of input arrays protected val probability: LongArray, protected val alias: IntArray @@ -102,17 +101,16 @@ open class AliasMethodDiscreteSampler private constructor( if (generator.nextLong() ushr 11 < probability[j]) j else alias[j] } - override fun toString(): String = "Alias method" + public override fun toString(): String = "Alias method" - companion object { + public companion object { private const val DEFAULT_ALPHA = 0 private const val ZERO = 0.0 private const val ONE_AS_NUMERATOR = 1L shl 53 private const val CONVERT_TO_NUMERATOR: Double = ONE_AS_NUMERATOR.toDouble() private const val MAX_SMALL_POWER_2_SIZE = 1 shl 11 - @JvmOverloads - fun of( + public fun of( probabilities: DoubleArray, alpha: Int = DEFAULT_ALPHA ): Sampler { diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt index a2d10e9f1..50a7b00c2 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/BoxMullerNormalizedGaussianSampler.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers -import scientifik.kmath.chains.Chain -import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.Sampler -import scientifik.kmath.prob.chain +import kscience.kmath.chains.Chain +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.Sampler +import kscience.kmath.prob.chain import kotlin.math.* /** @@ -13,10 +13,10 @@ import kotlin.math.* * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.html */ -class BoxMullerNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { +public class BoxMullerNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { private var nextGaussian: Double = Double.NaN - override fun sample(generator: RandomGenerator): Chain = generator.chain { + public override fun sample(generator: RandomGenerator): Chain = generator.chain { val random: Double if (nextGaussian.isNaN()) { @@ -40,9 +40,9 @@ class BoxMullerNormalizedGaussianSampler private constructor() : NormalizedGauss random } - override fun toString(): String = "Box-Muller normalized Gaussian deviate" + public override fun toString(): String = "Box-Muller normalized Gaussian deviate" - companion object { - fun of(): BoxMullerNormalizedGaussianSampler = BoxMullerNormalizedGaussianSampler() + public companion object { + public fun of(): BoxMullerNormalizedGaussianSampler = BoxMullerNormalizedGaussianSampler() } } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/GaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/GaussianSampler.kt index 2516f0480..1a0ccac90 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/GaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/GaussianSampler.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers -import scientifik.kmath.chains.Chain -import scientifik.kmath.chains.map -import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.Sampler +import kscience.kmath.chains.Chain +import kscience.kmath.chains.map +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.Sampler /** * Sampling from a Gaussian distribution with given mean and standard deviation. @@ -11,24 +11,24 @@ import scientifik.kmath.prob.Sampler * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/GaussianSampler.html */ -class GaussianSampler private constructor( +public class GaussianSampler private constructor( private val mean: Double, private val standardDeviation: Double, private val normalized: NormalizedGaussianSampler ) : Sampler { - override fun sample(generator: RandomGenerator): Chain = normalized + public override fun sample(generator: RandomGenerator): Chain = normalized .sample(generator) .map { standardDeviation * it + mean } override fun toString(): String = "Gaussian deviate [$normalized]" - companion object { - fun of( + public companion object { + public fun of( mean: Double, standardDeviation: Double, - normalized: NormalizedGaussianSampler + normalized: NormalizedGaussianSampler = ZigguratNormalizedGaussianSampler.of() ): GaussianSampler { - require(standardDeviation > 0) { "standard deviation is not strictly positive: $standardDeviation" } + require(standardDeviation > 0.0) { "standard deviation is not strictly positive: $standardDeviation" } return GaussianSampler( mean, diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalGamma.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalGamma.kt index 50c5f4ce0..16a5c96e0 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalGamma.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalGamma.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers import kotlin.math.PI import kotlin.math.ln diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalUtils.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalUtils.kt index 611c4064d..08a321b75 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalUtils.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalUtils.kt @@ -1,4 +1,4 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers import kotlin.math.ln import kotlin.math.min diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt index bb1dfa0c2..624fc9a7e 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/KempSmallMeanPoissonSampler.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers -import scientifik.kmath.chains.Chain -import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.Sampler -import scientifik.kmath.prob.chain +import kscience.kmath.chains.Chain +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.Sampler +import kscience.kmath.prob.chain import kotlin.math.exp /** @@ -18,11 +18,11 @@ import kotlin.math.exp * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.html */ -class KempSmallMeanPoissonSampler private constructor( +public class KempSmallMeanPoissonSampler private constructor( private val p0: Double, private val mean: Double ) : Sampler { - override fun sample(generator: RandomGenerator): Chain = generator.chain { + public override fun sample(generator: RandomGenerator): Chain = generator.chain { // Note on the algorithm: // - X is the unknown sample deviate (the output of the algorithm) // - x is the current value from the distribution @@ -48,10 +48,10 @@ class KempSmallMeanPoissonSampler private constructor( x } - override fun toString(): String = "Kemp Small Mean Poisson deviate" + public override fun toString(): String = "Kemp Small Mean Poisson deviate" - companion object { - fun of(mean: Double): KempSmallMeanPoissonSampler { + public companion object { + public fun of(mean: Double): KempSmallMeanPoissonSampler { require(mean > 0) { "Mean is not strictly positive: $mean" } val p0 = exp(-mean) // Probability must be positive. As mean increases then p(0) decreases. diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/LargeMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/LargeMeanPoissonSampler.kt index eafe28b39..dba2550cb 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/LargeMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/LargeMeanPoissonSampler.kt @@ -1,11 +1,11 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers -import scientifik.kmath.chains.Chain -import scientifik.kmath.chains.ConstantChain -import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.Sampler -import scientifik.kmath.prob.chain -import scientifik.kmath.prob.next +import kscience.kmath.chains.Chain +import kscience.kmath.chains.ConstantChain +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.Sampler +import kscience.kmath.prob.chain +import kscience.kmath.prob.next import kotlin.math.* /** @@ -19,7 +19,7 @@ import kotlin.math.* * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/LargeMeanPoissonSampler.html */ -class LargeMeanPoissonSampler private constructor(val mean: Double) : Sampler { +public class LargeMeanPoissonSampler private constructor(public val mean: Double) : Sampler { private val exponential: Sampler = AhrensDieterExponentialSampler.of(1.0) private val gaussian: Sampler = ZigguratNormalizedGaussianSampler.of() private val factorialLog: InternalUtils.FactorialLog = NO_CACHE_FACTORIAL_LOG @@ -41,7 +41,7 @@ class LargeMeanPoissonSampler private constructor(val mean: Double) : Sampler = generator.chain { + public override fun sample(generator: RandomGenerator): Chain = generator.chain { // This will never be null. It may be a no-op delegate that returns zero. val y2 = smallMeanPoissonSampler.next(generator) var x: Double @@ -114,7 +114,7 @@ class LargeMeanPoissonSampler private constructor(val mean: Double) : Sampler = ConstantChain(0) } - fun of(mean: Double): LargeMeanPoissonSampler { + public fun of(mean: Double): LargeMeanPoissonSampler { require(mean >= 1) { "mean is not >= 1: $mean" } // The algorithm is not valid if Math.floor(mean) is not an integer. require(mean <= MAX_MEAN) { "mean $mean > $MAX_MEAN" } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt index eec791906..69c04c20b 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/MarsagliaNormalizedGaussianSampler.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers -import scientifik.kmath.chains.Chain -import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.Sampler -import scientifik.kmath.prob.chain +import kscience.kmath.chains.Chain +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.Sampler +import kscience.kmath.prob.chain import kotlin.math.ln import kotlin.math.sqrt @@ -15,10 +15,10 @@ import kotlin.math.sqrt * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.html */ -class MarsagliaNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { +public class MarsagliaNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { private var nextGaussian = Double.NaN - override fun sample(generator: RandomGenerator): Chain = generator.chain { + public override fun sample(generator: RandomGenerator): Chain = generator.chain { if (nextGaussian.isNaN()) { val alpha: Double var x: Double @@ -53,9 +53,9 @@ class MarsagliaNormalizedGaussianSampler private constructor() : NormalizedGauss } } - override fun toString(): String = "Box-Muller (with rejection) normalized Gaussian deviate" + public override fun toString(): String = "Box-Muller (with rejection) normalized Gaussian deviate" - companion object { - fun of(): MarsagliaNormalizedGaussianSampler = MarsagliaNormalizedGaussianSampler() + public companion object { + public fun of(): MarsagliaNormalizedGaussianSampler = MarsagliaNormalizedGaussianSampler() } } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/NormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/NormalizedGaussianSampler.kt index 0ead77b5a..af2ab876d 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/NormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/NormalizedGaussianSampler.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers -import scientifik.kmath.prob.Sampler +import kscience.kmath.prob.Sampler /** * Marker interface for a sampler that generates values from an N(0,1) * [Gaussian distribution](https://en.wikipedia.org/wiki/Normal_distribution). */ -interface NormalizedGaussianSampler : Sampler +public interface NormalizedGaussianSampler : Sampler diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/PoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/PoissonSampler.kt index 4648940e1..02d8d5632 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/PoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/PoissonSampler.kt @@ -1,8 +1,8 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers -import scientifik.kmath.chains.Chain -import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.Sampler +import kscience.kmath.chains.Chain +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.Sampler /** * Sampler for the Poisson distribution. @@ -16,17 +16,15 @@ import scientifik.kmath.prob.Sampler * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/PoissonSampler.html */ -class PoissonSampler private constructor( - mean: Double -) : Sampler { +public class PoissonSampler private constructor(mean: Double) : Sampler { private val poissonSamplerDelegate: Sampler = of(mean) - override fun sample(generator: RandomGenerator): Chain = poissonSamplerDelegate.sample(generator) - override fun toString(): String = poissonSamplerDelegate.toString() + public override fun sample(generator: RandomGenerator): Chain = poissonSamplerDelegate.sample(generator) + public override fun toString(): String = poissonSamplerDelegate.toString() - companion object { + public companion object { private const val PIVOT = 40.0 - fun of(mean: Double) =// Each sampler should check the input arguments. + public fun of(mean: Double): Sampler =// Each sampler should check the input arguments. if (mean < PIVOT) SmallMeanPoissonSampler.of(mean) else LargeMeanPoissonSampler.of(mean) } } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/SmallMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/SmallMeanPoissonSampler.kt index f5b0eef68..ff4233288 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/SmallMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/SmallMeanPoissonSampler.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers -import scientifik.kmath.chains.Chain -import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.Sampler -import scientifik.kmath.prob.chain +import kscience.kmath.chains.Chain +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.Sampler +import kscience.kmath.prob.chain import kotlin.math.ceil import kotlin.math.exp @@ -19,7 +19,7 @@ import kotlin.math.exp * * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/SmallMeanPoissonSampler.html */ -class SmallMeanPoissonSampler private constructor(mean: Double) : Sampler { +public class SmallMeanPoissonSampler private constructor(mean: Double) : Sampler { private val p0: Double = exp(-mean) private val limit: Int = (if (p0 > 0) @@ -27,7 +27,7 @@ class SmallMeanPoissonSampler private constructor(mean: Double) : Sampler { else throw IllegalArgumentException("No p(x=0) probability for mean: $mean")).toInt() - override fun sample(generator: RandomGenerator): Chain = generator.chain { + public override fun sample(generator: RandomGenerator): Chain = generator.chain { var n = 0 var r = 1.0 @@ -39,10 +39,10 @@ class SmallMeanPoissonSampler private constructor(mean: Double) : Sampler { n } - override fun toString(): String = "Small Mean Poisson deviate" + public override fun toString(): String = "Small Mean Poisson deviate" - companion object { - fun of(mean: Double): SmallMeanPoissonSampler { + public companion object { + public fun of(mean: Double): SmallMeanPoissonSampler { require(mean > 0) { "mean is not strictly positive: $mean" } return SmallMeanPoissonSampler(mean) } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt index 421555d64..c9103ba86 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt @@ -1,9 +1,9 @@ -package scientifik.kmath.prob.samplers +package kscience.kmath.prob.samplers -import scientifik.kmath.chains.Chain -import scientifik.kmath.prob.RandomGenerator -import scientifik.kmath.prob.Sampler -import scientifik.kmath.prob.chain +import kscience.kmath.chains.Chain +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.Sampler +import kscience.kmath.prob.chain import kotlin.math.* /** @@ -14,7 +14,7 @@ import kotlin.math.* * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.html */ -class ZigguratNormalizedGaussianSampler private constructor() : +public class ZigguratNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { private fun sampleOne(generator: RandomGenerator): Double { @@ -23,9 +23,8 @@ class ZigguratNormalizedGaussianSampler private constructor() : return if (abs(j) < K[i]) j * W[i] else fix(generator, j, i) } - override fun sample(generator: RandomGenerator): Chain = generator.chain { sampleOne(this) } - - override fun toString(): String = "Ziggurat normalized Gaussian deviate" + public override fun sample(generator: RandomGenerator): Chain = generator.chain { sampleOne(this) } + public override fun toString(): String = "Ziggurat normalized Gaussian deviate" private fun fix( generator: RandomGenerator, @@ -59,7 +58,7 @@ class ZigguratNormalizedGaussianSampler private constructor() : } } - companion object { + public companion object { private const val R: Double = 3.442619855899 private const val ONE_OVER_R: Double = 1 / R private const val V: Double = 9.91256303526217e-3 @@ -94,7 +93,7 @@ class ZigguratNormalizedGaussianSampler private constructor() : } } - fun of(): ZigguratNormalizedGaussianSampler = ZigguratNormalizedGaussianSampler() + public fun of(): ZigguratNormalizedGaussianSampler = ZigguratNormalizedGaussianSampler() private fun gauss(x: Double): Double = exp(-0.5 * x * x) } } diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt deleted file mode 100644 index ae3f918ff..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/FactorizedDistribution.kt +++ /dev/null @@ -1,46 +0,0 @@ -package scientifik.kmath.prob - -import scientifik.kmath.chains.Chain -import scientifik.kmath.chains.SimpleChain - -/** - * A multivariate distribution which takes a map of parameters - */ -interface NamedDistribution : Distribution> - -/** - * A multivariate distribution that has independent distributions for separate axis - */ -class FactorizedDistribution(val distributions: Collection>) : NamedDistribution { - override fun probability(arg: Map): Double { - return distributions.fold(1.0) { acc, distr -> acc * distr.probability(arg) } - } - - override fun sample(generator: RandomGenerator): Chain> { - val chains = distributions.map { it.sample(generator) } - return SimpleChain> { - chains.fold(emptyMap()) { acc, chain -> acc + chain.next() } - } - } -} - -class NamedDistributionWrapper(val name: String, val distribution: Distribution) : NamedDistribution { - override fun probability(arg: Map): Double = distribution.probability( - arg[name] ?: error("Argument with name $name not found in input parameters") - ) - - override fun sample(generator: RandomGenerator): Chain> { - val chain = distribution.sample(generator) - return SimpleChain { - mapOf(name to chain.next()) - } - } -} - -class DistributionBuilder{ - private val distributions = ArrayList>() - - infix fun String.to(distribution: Distribution){ - distributions.add(NamedDistributionWrapper(this,distribution)) - } -} \ No newline at end of file diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt deleted file mode 100644 index 68602e1ea..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt +++ /dev/null @@ -1,30 +0,0 @@ -package scientifik.kmath.prob - -import scientifik.kmath.chains.BlockingIntChain -import scientifik.kmath.chains.BlockingRealChain -import scientifik.kmath.chains.Chain - -/** - * A possibly stateful chain producing random values. - */ -class RandomChain(val generator: RandomGenerator, private val gen: suspend RandomGenerator.() -> R) : Chain { - override suspend fun next(): R = generator.gen() - - override fun fork(): Chain = RandomChain(generator.fork(), gen) -} - -fun RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain = RandomChain(this, gen) - -fun RandomChain.blocking(): BlockingRealChain = let { - object : BlockingRealChain() { - override suspend fun next(): Double = it.next() - override fun fork(): Chain = it.fork() - } -} - -fun RandomChain.blocking(): BlockingIntChain = let { - object : BlockingIntChain() { - override suspend fun next(): Int = it.next() - override fun fork(): Chain = it.fork() - } -} diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt deleted file mode 100644 index 6bdabed9d..000000000 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt +++ /dev/null @@ -1,47 +0,0 @@ -package scientifik.kmath.prob - -import kotlin.random.Random - -/** - * A basic generator - */ -interface RandomGenerator { - fun nextBoolean(): Boolean - fun nextDouble(): Double - fun nextInt(): Int - fun nextInt(until: Int): Int - fun nextLong(): Long - fun nextLong(until: Long): Long - fun fillBytes(array: ByteArray, fromIndex: Int = 0, toIndex: Int = array.size) - fun nextBytes(size: Int): ByteArray = ByteArray(size).also { fillBytes(it) } - - /** - * Create a new generator which is independent from current generator (operations on new generator do not affect this one - * and vise versa). The statistical properties of new generator should be the same as for this one. - * For pseudo-random generator, the fork is keeping the same sequence of numbers for given call order for each run. - * - * The thread safety of this operation is not guaranteed since it could affect the state of the generator. - */ - fun fork(): RandomGenerator - - companion object { - val default by lazy { DefaultGenerator() } - fun default(seed: Long) = DefaultGenerator(Random(seed)) - } -} - -inline class DefaultGenerator(private val random: Random = Random) : RandomGenerator { - override fun nextBoolean(): Boolean = random.nextBoolean() - override fun nextDouble(): Double = random.nextDouble() - override fun nextInt(): Int = random.nextInt() - override fun nextInt(until: Int): Int = random.nextInt(until) - override fun nextLong(): Long = random.nextLong() - override fun nextLong(until: Long): Long = random.nextLong(until) - - override fun fillBytes(array: ByteArray, fromIndex: Int, toIndex: Int) { - random.nextBytes(array, fromIndex, toIndex) - } - - override fun nextBytes(size: Int): ByteArray = random.nextBytes(size) - override fun fork(): RandomGenerator = RandomGenerator.default(random.nextLong()) -} diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt index 797c932ad..67007358a 100644 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt +++ b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt @@ -1,21 +1,22 @@ package scientifik.kmath.prob +import kscience.kmath.prob.RandomGenerator import org.apache.commons.rng.simple.RandomSource -class RandomSourceGenerator(private val source: RandomSource, seed: Long?) : +public class RandomSourceGenerator(private val source: RandomSource, seed: Long?) : RandomGenerator { private val random = seed?.let { RandomSource.create(source, seed) } ?: RandomSource.create(source) - override fun nextBoolean(): Boolean = random.nextBoolean() - override fun nextDouble(): Double = random.nextDouble() - override fun nextInt(): Int = random.nextInt() - override fun nextInt(until: Int): Int = random.nextInt(until) - override fun nextLong(): Long = random.nextLong() - override fun nextLong(until: Long): Long = random.nextLong(until) + public override fun nextBoolean(): Boolean = random.nextBoolean() + public override fun nextDouble(): Double = random.nextDouble() + public override fun nextInt(): Int = random.nextInt() + public override fun nextInt(until: Int): Int = random.nextInt(until) + public override fun nextLong(): Long = random.nextLong() + public override fun nextLong(until: Long): Long = random.nextLong(until) - override fun fillBytes(array: ByteArray, fromIndex: Int, toIndex: Int) { + public override fun fillBytes(array: ByteArray, fromIndex: Int, toIndex: Int) { require(toIndex > fromIndex) random.nextBytes(array, fromIndex, toIndex - fromIndex) } @@ -23,8 +24,8 @@ class RandomSourceGenerator(private val source: RandomSource, seed: Long?) : override fun fork(): RandomGenerator = RandomSourceGenerator(source, nextLong()) } -fun RandomGenerator.Companion.fromSource(source: RandomSource, seed: Long? = null): RandomSourceGenerator = +public fun RandomGenerator.Companion.fromSource(source: RandomSource, seed: Long? = null): RandomSourceGenerator = RandomSourceGenerator(source, seed) -fun RandomGenerator.Companion.mersenneTwister(seed: Long? = null): RandomSourceGenerator = +public fun RandomGenerator.Companion.mersenneTwister(seed: Long? = null): RandomSourceGenerator = fromSource(RandomSource.MT, seed) diff --git a/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/CommonsDistributionsTest.kt b/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/CommonsDistributionsTest.kt index 12a00684b..02fac366e 100644 --- a/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/CommonsDistributionsTest.kt +++ b/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/CommonsDistributionsTest.kt @@ -3,25 +3,24 @@ package kscience.kmath.prob import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.toList import kotlinx.coroutines.runBlocking +import kscience.kmath.prob.samplers.GaussianSampler import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test internal class CommonsDistributionsTest { @Test fun testNormalDistributionSuspend() { - val distribution = Distribution.normal(7.0, 2.0) + val distribution = GaussianSampler.of(7.0, 2.0) val generator = RandomGenerator.default(1) - val sample = runBlocking { - distribution.sample(generator).take(1000).toList() - } + val sample = runBlocking { distribution.sample(generator).take(1000).toList() } Assertions.assertEquals(7.0, sample.average(), 0.1) } @Test fun testNormalDistributionBlocking() { - val distribution = Distribution.normal(7.0, 2.0) + val distribution = GaussianSampler.of(7.0, 2.0) val generator = RandomGenerator.default(1) - val sample = distribution.sample(generator).nextBlock(1000) + val sample = runBlocking { distribution.sample(generator).blocking().nextBlock(1000) } Assertions.assertEquals(7.0, sample.average(), 0.1) } } From b83293a057bba9b65f0e72920b68af846307f436 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 27 Sep 2020 15:52:18 +0700 Subject: [PATCH 014/393] Update example --- .../commons/prob/DistributionBenchmark.kt | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt index 8f68a9d3f..e4a5bc534 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt @@ -3,19 +3,20 @@ package kscience.kmath.commons.prob import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking -import org.apache.commons.rng.simple.RandomSource -import kscience.kmath.prob.RandomChain import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.blocking import kscience.kmath.prob.fromSource +import kscience.kmath.prob.samplers.GaussianSampler +import org.apache.commons.rng.simple.RandomSource import java.time.Duration import java.time.Instant -import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler as ApacheZigguratNormalizedGaussianSampler -import kscience.kmath.prob.samplers.ZigguratNormalizedGaussianSampler as KMathZigguratNormalizedGaussianSampler +import org.apache.commons.rng.sampling.distribution.GaussianSampler as CMGaussianSampler +import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler as CMZigguratNormalizedGaussianSampler private suspend fun runKMathChained(): Duration { val generator = RandomGenerator.fromSource(RandomSource.MT, 123L) - val normal = KMathZigguratNormalizedGaussianSampler.of() - val chain = normal.sample(generator) as RandomChain + val normal = GaussianSampler.of(7.0, 2.0) + val chain = normal.sample(generator).blocking() val startTime = Instant.now() var sum = 0.0 @@ -28,17 +29,23 @@ private suspend fun runKMathChained(): Duration { println("Chain sampler completed $counter elements in $duration: $meanValue") } } + return Duration.between(startTime, Instant.now()) } private fun runApacheDirect(): Duration { val rng = RandomSource.create(RandomSource.MT, 123L) - val sampler = ApacheZigguratNormalizedGaussianSampler.of(rng) + + val sampler = CMGaussianSampler.of( + CMZigguratNormalizedGaussianSampler.of(rng), + 7.0, + 2.0 + ) + val startTime = Instant.now() - var sum = 0.0 - repeat(10000001) { counter -> + repeat(10000001) { counter -> sum += sampler.sample() if (counter % 100000 == 0) { @@ -47,17 +54,16 @@ private fun runApacheDirect(): Duration { println("Direct sampler completed $counter elements in $duration: $meanValue") } } + return Duration.between(startTime, Instant.now()) } /** * Comparing chain sampling performance with direct sampling performance */ -fun main() { - runBlocking(Dispatchers.Default) { - val chainJob = async { runKMathChained() } - val directJob = async { runApacheDirect() } - println("KMath Chained: ${chainJob.await()}") - println("Apache Direct: ${directJob.await()}") - } +fun main(): Unit = runBlocking(Dispatchers.Default) { + val chainJob = async { runKMathChained() } + val directJob = async { runApacheDirect() } + println("KMath Chained: ${chainJob.await()}") + println("Apache Direct: ${directJob.await()}") } From 0c6fff3878d71c23f1254cb52e5a3139ac0f4697 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 15 Oct 2020 23:52:50 +0700 Subject: [PATCH 015/393] Code refactoring, implement NormalDistribution --- .../commons/expressions/DiffExpression.kt | 6 +- .../kscience/kmath/prob/Distribution.kt | 12 +-- .../prob/distributions/NormalDistribution.kt | 30 ++++++++ .../AhrensDieterExponentialSampler.kt | 1 + .../samplers/AliasMethodDiscreteSampler.kt | 1 + .../kmath/prob/samplers/GaussianSampler.kt | 7 +- .../kmath/prob/samplers/InternalGamma.kt | 41 ---------- .../kmath/prob/samplers/InternalUtils.kt | 76 ------------------- .../prob/samplers/LargeMeanPoissonSampler.kt | 8 +- .../kmath/prob/RandomSourceGenerator.kt | 5 +- 10 files changed, 45 insertions(+), 142 deletions(-) create mode 100644 kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/distributions/NormalDistribution.kt diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt index c39f0d04c..601675167 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/expressions/DiffExpression.kt @@ -33,10 +33,7 @@ public class DerivativeStructureField( variables[name] ?: default ?: error("A variable with name $name does not exist") public fun Number.const(): DerivativeStructure = DerivativeStructure(order, parameters.size, toDouble()) - - public fun DerivativeStructure.deriv(parName: String, order: Int = 1): Double { - return deriv(mapOf(parName to order)) - } + public fun DerivativeStructure.deriv(parName: String, order: Int = 1): Double = deriv(mapOf(parName to order)) public fun DerivativeStructure.deriv(orders: Map): Double { return getPartialDerivative(*parameters.keys.map { orders[it] ?: 0 }.toIntArray()) @@ -75,7 +72,6 @@ public class DerivativeStructureField( public fun power(arg: DerivativeStructure, pow: DerivativeStructure): DerivativeStructure = arg.pow(pow) public override fun exp(arg: DerivativeStructure): DerivativeStructure = arg.exp() public override fun ln(arg: DerivativeStructure): DerivativeStructure = arg.log() - public override operator fun DerivativeStructure.plus(b: Number): DerivativeStructure = add(b.toDouble()) public override operator fun DerivativeStructure.minus(b: Number): DerivativeStructure = subtract(b.toDouble()) public override operator fun Number.plus(b: DerivativeStructure): DerivativeStructure = b + this diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt index 965635e09..bbb1de1e3 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt @@ -6,7 +6,7 @@ import kscience.kmath.chains.collect import kscience.kmath.structures.Buffer import kscience.kmath.structures.BufferFactory -public interface Sampler { +public fun interface Sampler { public fun sample(generator: RandomGenerator): Chain } @@ -20,11 +20,7 @@ public interface Distribution : Sampler { */ public fun probability(arg: T): Double - /** - * Create a chain of samples from this distribution. - * The chain is not guaranteed to be stateless, but different sample chains should be independent. - */ - override fun sample(generator: RandomGenerator): Chain + public override fun sample(generator: RandomGenerator): Chain /** * An empty companion. Distribution factories should be written as its extensions @@ -63,9 +59,7 @@ public fun Sampler.sampleBuffer( //clear list from previous run tmp.clear() //Fill list - repeat(size) { - tmp.add(chain.next()) - } + repeat(size) { tmp.add(chain.next()) } //return new buffer with elements from tmp bufferFactory(size) { tmp[it] } } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/distributions/NormalDistribution.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/distributions/NormalDistribution.kt new file mode 100644 index 000000000..095ac5ea9 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/distributions/NormalDistribution.kt @@ -0,0 +1,30 @@ +package kscience.kmath.prob.distributions + +import kscience.kmath.chains.Chain +import kscience.kmath.prob.RandomGenerator +import kscience.kmath.prob.UnivariateDistribution +import kscience.kmath.prob.internal.InternalErf +import kscience.kmath.prob.samplers.GaussianSampler +import kotlin.math.* + +public inline class NormalDistribution(public val sampler: GaussianSampler) : UnivariateDistribution { + public override fun probability(arg: Double): Double { + val x1 = (arg - sampler.mean) / sampler.standardDeviation + return exp(-0.5 * x1 * x1 - (ln(sampler.standardDeviation) + 0.5 * ln(2 * PI))) + } + + public override fun sample(generator: RandomGenerator): Chain = sampler.sample(generator) + + public override fun cumulative(arg: Double): Double { + val dev = arg - sampler.mean + + return when { + abs(dev) > 40 * sampler.standardDeviation -> if (dev < 0) 0.0 else 1.0 + else -> 0.5 * InternalErf.erfc(-dev / (sampler.standardDeviation * SQRT2)) + } + } + + private companion object { + private val SQRT2 = sqrt(2.0) + } +} diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AhrensDieterExponentialSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AhrensDieterExponentialSampler.kt index dc388a3ea..d4b443e9c 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AhrensDieterExponentialSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AhrensDieterExponentialSampler.kt @@ -4,6 +4,7 @@ import kscience.kmath.chains.Chain import kscience.kmath.prob.RandomGenerator import kscience.kmath.prob.Sampler import kscience.kmath.prob.chain +import kscience.kmath.prob.internal.InternalUtils import kotlin.math.ln import kotlin.math.pow diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AliasMethodDiscreteSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AliasMethodDiscreteSampler.kt index c5eed2990..f04b5bcb0 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AliasMethodDiscreteSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AliasMethodDiscreteSampler.kt @@ -4,6 +4,7 @@ import kscience.kmath.chains.Chain import kscience.kmath.prob.RandomGenerator import kscience.kmath.prob.Sampler import kscience.kmath.prob.chain +import kscience.kmath.prob.internal.InternalUtils import kotlin.math.ceil import kotlin.math.max import kotlin.math.min diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/GaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/GaussianSampler.kt index 1a0ccac90..1a5e4cfdd 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/GaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/GaussianSampler.kt @@ -10,10 +10,13 @@ import kscience.kmath.prob.Sampler * * Based on Commons RNG implementation. * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/GaussianSampler.html + * + * @property mean the mean of the distribution. + * @property standardDeviation the variance of the distribution. */ public class GaussianSampler private constructor( - private val mean: Double, - private val standardDeviation: Double, + public val mean: Double, + public val standardDeviation: Double, private val normalized: NormalizedGaussianSampler ) : Sampler { public override fun sample(generator: RandomGenerator): Chain = normalized diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalGamma.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalGamma.kt index 16a5c96e0..d970d1447 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalGamma.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalGamma.kt @@ -1,43 +1,2 @@ package kscience.kmath.prob.samplers -import kotlin.math.PI -import kotlin.math.ln - -internal object InternalGamma { - private const val LANCZOS_G = 607.0 / 128.0 - - private val LANCZOS_COEFFICIENTS = doubleArrayOf( - 0.99999999999999709182, - 57.156235665862923517, - -59.597960355475491248, - 14.136097974741747174, - -0.49191381609762019978, - .33994649984811888699e-4, - .46523628927048575665e-4, - -.98374475304879564677e-4, - .15808870322491248884e-3, - -.21026444172410488319e-3, - .21743961811521264320e-3, - -.16431810653676389022e-3, - .84418223983852743293e-4, - -.26190838401581408670e-4, - .36899182659531622704e-5 - ) - - private val HALF_LOG_2_PI: Double = 0.5 * ln(2.0 * PI) - - fun logGamma(x: Double): Double { - // Stripped-down version of the same method defined in "Commons Math": - // Unused "if" branches (for when x < 8) have been removed here since - // this method is only used (by class "InternalUtils") in order to - // compute log(n!) for x > 20. - val sum = lanczos(x) - val tmp = x + LANCZOS_G + 0.5 - return (x + 0.5) * ln(tmp) - tmp + HALF_LOG_2_PI + ln(sum / x) - } - - private fun lanczos(x: Double): Double { - val sum = (LANCZOS_COEFFICIENTS.size - 1 downTo 1).sumByDouble { LANCZOS_COEFFICIENTS[it] / (x + it) } - return sum + LANCZOS_COEFFICIENTS[0] - } -} diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalUtils.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalUtils.kt index 08a321b75..d970d1447 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalUtils.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalUtils.kt @@ -1,78 +1,2 @@ package kscience.kmath.prob.samplers -import kotlin.math.ln -import kotlin.math.min - -internal object InternalUtils { - private val FACTORIALS = longArrayOf( - 1L, 1L, 2L, - 6L, 24L, 120L, - 720L, 5040L, 40320L, - 362880L, 3628800L, 39916800L, - 479001600L, 6227020800L, 87178291200L, - 1307674368000L, 20922789888000L, 355687428096000L, - 6402373705728000L, 121645100408832000L, 2432902008176640000L - ) - - private const val BEGIN_LOG_FACTORIALS = 2 - - fun factorial(n: Int): Long = FACTORIALS[n] - - fun validateProbabilities(probabilities: DoubleArray?): Double { - require(!(probabilities == null || probabilities.isEmpty())) { "Probabilities must not be empty." } - var sumProb = 0.0 - - probabilities.forEach { prob -> - validateProbability(prob) - sumProb += prob - } - - require(!(sumProb.isInfinite() || sumProb <= 0)) { "Invalid sum of probabilities: $sumProb" } - return sumProb - } - - private fun validateProbability(probability: Double): Unit = - require(!(probability < 0 || probability.isInfinite() || probability.isNaN())) { "Invalid probability: $probability" } - - class FactorialLog private constructor( - numValues: Int, - cache: DoubleArray? - ) { - private val logFactorials: DoubleArray = DoubleArray(numValues) - - init { - val endCopy: Int - - if (cache != null && cache.size > BEGIN_LOG_FACTORIALS) { - // Copy available values. - endCopy = min(cache.size, numValues) - cache.copyInto( - logFactorials, - BEGIN_LOG_FACTORIALS, - BEGIN_LOG_FACTORIALS, endCopy - ) - } - // All values to be computed - else endCopy = BEGIN_LOG_FACTORIALS - - // Compute remaining values. - (endCopy until numValues).forEach { i -> - if (i < FACTORIALS.size) - logFactorials[i] = ln(FACTORIALS[i].toDouble()) - else - logFactorials[i] = logFactorials[i - 1] + ln(i.toDouble()) - } - } - - fun value(n: Int): Double { - if (n < logFactorials.size) - return logFactorials[n] - - return if (n < FACTORIALS.size) ln(FACTORIALS[n].toDouble()) else InternalGamma.logGamma(n + 1.0) - } - - companion object { - fun create(): FactorialLog = FactorialLog(0, null) - } - } -} diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/LargeMeanPoissonSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/LargeMeanPoissonSampler.kt index dba2550cb..8a54fabaa 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/LargeMeanPoissonSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/LargeMeanPoissonSampler.kt @@ -5,6 +5,7 @@ import kscience.kmath.chains.ConstantChain import kscience.kmath.prob.RandomGenerator import kscience.kmath.prob.Sampler import kscience.kmath.prob.chain +import kscience.kmath.prob.internal.InternalUtils import kscience.kmath.prob.next import kotlin.math.* @@ -111,16 +112,13 @@ public class LargeMeanPoissonSampler private constructor(public val mean: Double } private fun getFactorialLog(n: Int): Double = factorialLog.value(n) - - override fun toString(): String = "Large Mean Poisson deviate" + public override fun toString(): String = "Large Mean Poisson deviate" public companion object { private const val MAX_MEAN: Double = 0.5 * Int.MAX_VALUE private val NO_CACHE_FACTORIAL_LOG: InternalUtils.FactorialLog = InternalUtils.FactorialLog.create() - private val NO_SMALL_MEAN_POISSON_SAMPLER: Sampler = object : Sampler { - override fun sample(generator: RandomGenerator): Chain = ConstantChain(0) - } + private val NO_SMALL_MEAN_POISSON_SAMPLER: Sampler = Sampler { ConstantChain(0) } public fun of(mean: Double): LargeMeanPoissonSampler { require(mean >= 1) { "mean is not >= 1: $mean" } diff --git a/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt b/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt index 18be6f019..9cdde6b4b 100644 --- a/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt +++ b/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt @@ -26,10 +26,7 @@ public class RandomSourceGenerator(public val source: RandomSource, seed: Long?) public inline class RandomGeneratorProvider(public val generator: RandomGenerator) : UniformRandomProvider { public override fun nextBoolean(): Boolean = generator.nextBoolean() public override fun nextFloat(): Float = generator.nextDouble().toFloat() - - public override fun nextBytes(bytes: ByteArray) { - generator.fillBytes(bytes) - } + public override fun nextBytes(bytes: ByteArray): Unit = generator.fillBytes(bytes) public override fun nextBytes(bytes: ByteArray, start: Int, len: Int) { generator.fillBytes(bytes, start, start + len) From d4aa4587a9a5f1b417db4d7b479151f8d5663ac0 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 15 Oct 2020 23:53:19 +0700 Subject: [PATCH 016/393] Add missing files --- .../kmath/prob/internal/InternalErf.kt | 11 + .../kmath/prob/internal/InternalGamma.kt | 245 ++++++++++++++++++ .../kmath/prob/internal/InternalUtils.kt | 78 ++++++ .../kmath/prob/RandomSourceGenerator.kt | 31 --- 4 files changed, 334 insertions(+), 31 deletions(-) create mode 100644 kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalErf.kt create mode 100644 kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalGamma.kt create mode 100644 kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalUtils.kt delete mode 100644 kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalErf.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalErf.kt new file mode 100644 index 000000000..178423e68 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalErf.kt @@ -0,0 +1,11 @@ +package kscience.kmath.prob.internal + +import kotlin.math.abs + +internal object InternalErf { + fun erfc(x: Double): Double { + if (abs(x) > 40) return if (x > 0) 0.0 else 2.0 + val ret = InternalGamma.regularizedGammaQ(0.5, x * x, 10000) + return if (x < 0) 2 - ret else ret + } +} \ No newline at end of file diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalGamma.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalGamma.kt new file mode 100644 index 000000000..7480d2396 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalGamma.kt @@ -0,0 +1,245 @@ +package kscience.kmath.prob.internal + +import kotlin.math.* + +private abstract class ContinuedFraction protected constructor() { + protected abstract fun getA(n: Int, x: Double): Double + protected abstract fun getB(n: Int, x: Double): Double + + fun evaluate(x: Double, maxIterations: Int): Double { + val small = 1e-50 + var hPrev = getA(0, x) + if (hPrev == 0.0 || abs(0.0 - hPrev) <= small) hPrev = small + var n = 1 + var dPrev = 0.0 + var cPrev = hPrev + var hN = hPrev + + while (n < maxIterations) { + val a = getA(n, x) + val b = getB(n, x) + var dN = a + b * dPrev + if (dN == 0.0 || abs(0.0 - dN) <= small) dN = small + var cN = a + b / cPrev + if (cN == 0.0 || abs(0.0 - cN) <= small) cN = small + dN = 1 / dN + val deltaN = cN * dN + hN = hPrev * deltaN + check(!hN.isInfinite()) { "hN is infinite" } + check(!hN.isNaN()) { "hN is NaN" } + if (abs(deltaN - 1.0) < 10e-9) break + dPrev = dN + cPrev = cN + hPrev = hN + n++ + } + + check(n < maxIterations) { "n is more than maxIterations" } + return hN + } +} + +internal object InternalGamma { + const val LANCZOS_G = 607.0 / 128.0 + + private val LANCZOS = doubleArrayOf( + 0.99999999999999709182, + 57.156235665862923517, + -59.597960355475491248, + 14.136097974741747174, + -0.49191381609762019978, + .33994649984811888699e-4, + .46523628927048575665e-4, + -.98374475304879564677e-4, + .15808870322491248884e-3, + -.21026444172410488319e-3, + .21743961811521264320e-3, + -.16431810653676389022e-3, + .84418223983852743293e-4, + -.26190838401581408670e-4, + .36899182659531622704e-5 + ) + + private val HALF_LOG_2_PI = 0.5 * ln(2.0 * PI) + private const val INV_GAMMA1P_M1_A0 = .611609510448141581788E-08 + private const val INV_GAMMA1P_M1_A1 = .624730830116465516210E-08 + private const val INV_GAMMA1P_M1_B1 = .203610414066806987300E+00 + private const val INV_GAMMA1P_M1_B2 = .266205348428949217746E-01 + private const val INV_GAMMA1P_M1_B3 = .493944979382446875238E-03 + private const val INV_GAMMA1P_M1_B4 = -.851419432440314906588E-05 + private const val INV_GAMMA1P_M1_B5 = -.643045481779353022248E-05 + private const val INV_GAMMA1P_M1_B6 = .992641840672773722196E-06 + private const val INV_GAMMA1P_M1_B7 = -.607761895722825260739E-07 + private const val INV_GAMMA1P_M1_B8 = .195755836614639731882E-09 + private const val INV_GAMMA1P_M1_P0 = .6116095104481415817861E-08 + private const val INV_GAMMA1P_M1_P1 = .6871674113067198736152E-08 + private const val INV_GAMMA1P_M1_P2 = .6820161668496170657918E-09 + private const val INV_GAMMA1P_M1_P3 = .4686843322948848031080E-10 + private const val INV_GAMMA1P_M1_P4 = .1572833027710446286995E-11 + private const val INV_GAMMA1P_M1_P5 = -.1249441572276366213222E-12 + private const val INV_GAMMA1P_M1_P6 = .4343529937408594255178E-14 + private const val INV_GAMMA1P_M1_Q1 = .3056961078365221025009E+00 + private const val INV_GAMMA1P_M1_Q2 = .5464213086042296536016E-01 + private const val INV_GAMMA1P_M1_Q3 = .4956830093825887312020E-02 + private const val INV_GAMMA1P_M1_Q4 = .2692369466186361192876E-03 + private const val INV_GAMMA1P_M1_C = -.422784335098467139393487909917598E+00 + private const val INV_GAMMA1P_M1_C0 = .577215664901532860606512090082402E+00 + private const val INV_GAMMA1P_M1_C1 = -.655878071520253881077019515145390E+00 + private const val INV_GAMMA1P_M1_C2 = -.420026350340952355290039348754298E-01 + private const val INV_GAMMA1P_M1_C3 = .166538611382291489501700795102105E+00 + private const val INV_GAMMA1P_M1_C4 = -.421977345555443367482083012891874E-01 + private const val INV_GAMMA1P_M1_C5 = -.962197152787697356211492167234820E-02 + private const val INV_GAMMA1P_M1_C6 = .721894324666309954239501034044657E-02 + private const val INV_GAMMA1P_M1_C7 = -.116516759185906511211397108401839E-02 + private const val INV_GAMMA1P_M1_C8 = -.215241674114950972815729963053648E-03 + private const val INV_GAMMA1P_M1_C9 = .128050282388116186153198626328164E-03 + private const val INV_GAMMA1P_M1_C10 = -.201348547807882386556893914210218E-04 + private const val INV_GAMMA1P_M1_C11 = -.125049348214267065734535947383309E-05 + private const val INV_GAMMA1P_M1_C12 = .113302723198169588237412962033074E-05 + private const val INV_GAMMA1P_M1_C13 = -.205633841697760710345015413002057E-06 + + fun logGamma(x: Double): Double { + val ret: Double + + when { + x.isNaN() || x <= 0.0 -> ret = Double.NaN + x < 0.5 -> return logGamma1p(x) - ln(x) + x <= 2.5 -> return logGamma1p(x - 0.5 - 0.5) + + x <= 8.0 -> { + val n = floor(x - 1.5).toInt() + var prod = 1.0 + (1..n).forEach { i -> prod *= x - i } + return logGamma1p(x - (n + 1)) + ln(prod) + } + + else -> { + val tmp = x + LANCZOS_G + .5 + ret = (x + .5) * ln(tmp) - tmp + HALF_LOG_2_PI + ln(lanczos(x) / x) + } + } + + return ret + } + + private fun regularizedGammaP( + a: Double, + x: Double, + maxIterations: Int = Int.MAX_VALUE + ): Double = when { + a.isNaN() || x.isNaN() || a <= 0.0 || x < 0.0 -> Double.NaN + x == 0.0 -> 0.0 + x >= a + 1 -> 1.0 - regularizedGammaQ(a, x, maxIterations) + + else -> { + // calculate series + var n = 0.0 // current element index + var an = 1.0 / a // n-th element in the series + var sum = an // partial sum + + while (abs(an / sum) > 10e-15 && n < maxIterations && sum < Double.POSITIVE_INFINITY) { + // compute next element in the series + n += 1.0 + an *= x / (a + n) + + // update partial sum + sum += an + } + + when { + n >= maxIterations -> throw error("Maximal iterations is exceeded $maxIterations") + sum.isInfinite() -> 1.0 + else -> exp(-x + a * ln(x) - logGamma(a)) * sum + } + } + } + + fun regularizedGammaQ( + a: Double, + x: Double, + maxIterations: Int = Int.MAX_VALUE + ): Double = when { + a.isNaN() || x.isNaN() || a <= 0.0 || x < 0.0 -> Double.NaN + x == 0.0 -> 1.0 + x < a + 1.0 -> 1.0 - regularizedGammaP(a, x, maxIterations) + + else -> 1.0 / object : ContinuedFraction() { + override fun getA(n: Int, x: Double): Double = 2.0 * n + 1.0 - a + x + override fun getB(n: Int, x: Double): Double = n * (a - n) + }.evaluate(x, maxIterations) * exp(-x + a * ln(x) - logGamma(a)) + } + + private fun lanczos(x: Double): Double = + (LANCZOS.size - 1 downTo 1).sumByDouble { LANCZOS[it] / (x + it) } + LANCZOS[0] + + private fun invGamma1pm1(x: Double): Double { + require(x >= -0.5) + require(x <= 1.5) + val ret: Double + val t = if (x <= 0.5) x else x - 0.5 - 0.5 + + if (t < 0.0) { + val a = INV_GAMMA1P_M1_A0 + t * INV_GAMMA1P_M1_A1 + var b = INV_GAMMA1P_M1_B8 + b = INV_GAMMA1P_M1_B7 + t * b + b = INV_GAMMA1P_M1_B6 + t * b + b = INV_GAMMA1P_M1_B5 + t * b + b = INV_GAMMA1P_M1_B4 + t * b + b = INV_GAMMA1P_M1_B3 + t * b + b = INV_GAMMA1P_M1_B2 + t * b + b = INV_GAMMA1P_M1_B1 + t * b + b = 1.0 + t * b + var c = INV_GAMMA1P_M1_C13 + t * (a / b) + c = INV_GAMMA1P_M1_C12 + t * c + c = INV_GAMMA1P_M1_C11 + t * c + c = INV_GAMMA1P_M1_C10 + t * c + c = INV_GAMMA1P_M1_C9 + t * c + c = INV_GAMMA1P_M1_C8 + t * c + c = INV_GAMMA1P_M1_C7 + t * c + c = INV_GAMMA1P_M1_C6 + t * c + c = INV_GAMMA1P_M1_C5 + t * c + c = INV_GAMMA1P_M1_C4 + t * c + c = INV_GAMMA1P_M1_C3 + t * c + c = INV_GAMMA1P_M1_C2 + t * c + c = INV_GAMMA1P_M1_C1 + t * c + c = INV_GAMMA1P_M1_C + t * c + ret = (if (x > 0.5) t * c / x else x * (c + 0.5 + 0.5)) + } else { + var p = INV_GAMMA1P_M1_P6 + p = INV_GAMMA1P_M1_P5 + t * p + p = INV_GAMMA1P_M1_P4 + t * p + p = INV_GAMMA1P_M1_P3 + t * p + p = INV_GAMMA1P_M1_P2 + t * p + p = INV_GAMMA1P_M1_P1 + t * p + p = INV_GAMMA1P_M1_P0 + t * p + var q = INV_GAMMA1P_M1_Q4 + q = INV_GAMMA1P_M1_Q3 + t * q + q = INV_GAMMA1P_M1_Q2 + t * q + q = INV_GAMMA1P_M1_Q1 + t * q + q = 1.0 + t * q + var c = INV_GAMMA1P_M1_C13 + p / q * t + c = INV_GAMMA1P_M1_C12 + t * c + c = INV_GAMMA1P_M1_C11 + t * c + c = INV_GAMMA1P_M1_C10 + t * c + c = INV_GAMMA1P_M1_C9 + t * c + c = INV_GAMMA1P_M1_C8 + t * c + c = INV_GAMMA1P_M1_C7 + t * c + c = INV_GAMMA1P_M1_C6 + t * c + c = INV_GAMMA1P_M1_C5 + t * c + c = INV_GAMMA1P_M1_C4 + t * c + c = INV_GAMMA1P_M1_C3 + t * c + c = INV_GAMMA1P_M1_C2 + t * c + c = INV_GAMMA1P_M1_C1 + t * c + c = INV_GAMMA1P_M1_C0 + t * c + ret = (if (x > 0.5) t / x * (c - 0.5 - 0.5) else x * c) + } + + return ret + } + + private fun logGamma1p(x: Double): Double { + require(x >= -0.5) + require(x <= 1.5) + return -ln1p(invGamma1pm1(x)) + } +} diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalUtils.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalUtils.kt new file mode 100644 index 000000000..655e284c0 --- /dev/null +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalUtils.kt @@ -0,0 +1,78 @@ +package kscience.kmath.prob.internal + +import kotlin.math.ln +import kotlin.math.min + +internal object InternalUtils { + private val FACTORIALS = longArrayOf( + 1L, 1L, 2L, + 6L, 24L, 120L, + 720L, 5040L, 40320L, + 362880L, 3628800L, 39916800L, + 479001600L, 6227020800L, 87178291200L, + 1307674368000L, 20922789888000L, 355687428096000L, + 6402373705728000L, 121645100408832000L, 2432902008176640000L + ) + + private const val BEGIN_LOG_FACTORIALS = 2 + + fun factorial(n: Int): Long = FACTORIALS[n] + + fun validateProbabilities(probabilities: DoubleArray?): Double { + require(!(probabilities == null || probabilities.isEmpty())) { "Probabilities must not be empty." } + var sumProb = 0.0 + + probabilities.forEach { prob -> + validateProbability(prob) + sumProb += prob + } + + require(!(sumProb.isInfinite() || sumProb <= 0)) { "Invalid sum of probabilities: $sumProb" } + return sumProb + } + + private fun validateProbability(probability: Double): Unit = + require(!(probability < 0 || probability.isInfinite() || probability.isNaN())) { "Invalid probability: $probability" } + + class FactorialLog private constructor( + numValues: Int, + cache: DoubleArray? + ) { + private val logFactorials: DoubleArray = DoubleArray(numValues) + + init { + val endCopy: Int + + if (cache != null && cache.size > BEGIN_LOG_FACTORIALS) { + // Copy available values. + endCopy = min(cache.size, numValues) + cache.copyInto( + logFactorials, + BEGIN_LOG_FACTORIALS, + BEGIN_LOG_FACTORIALS, endCopy + ) + } + // All values to be computed + else endCopy = BEGIN_LOG_FACTORIALS + + // Compute remaining values. + (endCopy until numValues).forEach { i -> + if (i < FACTORIALS.size) + logFactorials[i] = ln(FACTORIALS[i].toDouble()) + else + logFactorials[i] = logFactorials[i - 1] + ln(i.toDouble()) + } + } + + fun value(n: Int): Double { + if (n < logFactorials.size) + return logFactorials[n] + + return if (n < FACTORIALS.size) ln(FACTORIALS[n].toDouble()) else InternalGamma.logGamma(n + 1.0) + } + + companion object { + fun create(): FactorialLog = FactorialLog(0, null) + } + } +} \ No newline at end of file diff --git a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt b/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt deleted file mode 100644 index 67007358a..000000000 --- a/kmath-prob/src/jvmMain/kotlin/scientifik/kmath/prob/RandomSourceGenerator.kt +++ /dev/null @@ -1,31 +0,0 @@ -package scientifik.kmath.prob - -import kscience.kmath.prob.RandomGenerator -import org.apache.commons.rng.simple.RandomSource - -public class RandomSourceGenerator(private val source: RandomSource, seed: Long?) : - RandomGenerator { - private val random = seed?.let { - RandomSource.create(source, seed) - } ?: RandomSource.create(source) - - public override fun nextBoolean(): Boolean = random.nextBoolean() - public override fun nextDouble(): Double = random.nextDouble() - public override fun nextInt(): Int = random.nextInt() - public override fun nextInt(until: Int): Int = random.nextInt(until) - public override fun nextLong(): Long = random.nextLong() - public override fun nextLong(until: Long): Long = random.nextLong(until) - - public override fun fillBytes(array: ByteArray, fromIndex: Int, toIndex: Int) { - require(toIndex > fromIndex) - random.nextBytes(array, fromIndex, toIndex - fromIndex) - } - - override fun fork(): RandomGenerator = RandomSourceGenerator(source, nextLong()) -} - -public fun RandomGenerator.Companion.fromSource(source: RandomSource, seed: Long? = null): RandomSourceGenerator = - RandomSourceGenerator(source, seed) - -public fun RandomGenerator.Companion.mersenneTwister(seed: Long? = null): RandomSourceGenerator = - fromSource(RandomSource.MT, seed) From 612f6f00828e3595773d964902daa2c96e48fa4b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 16 Oct 2020 16:49:47 +0700 Subject: [PATCH 017/393] Refactor, remove unused files, remove BasicSampler --- .../structures/StructureReadBenchmark.kt | 2 +- kmath-core/build.gradle.kts | 12 ++- .../kscience/kmath/operations/BigInt.kt | 23 ++--- .../kscience/kmath/structures/Buffers.kt | 2 +- .../kscience/kmath/structures/Structure2D.kt | 3 +- .../kmath/structures/NumberNDFieldTest.kt | 3 +- .../kotlin/kscience/kmath/chains/Chain.kt | 20 ++--- .../kscience/kmath/streaming/BufferFlow.kt | 2 +- .../kscience/kmath/streaming/RingBuffer.kt | 8 +- .../kscience/kmath/functions/Piecewise.kt | 6 +- .../kscience/kmath/prob/Distribution.kt | 23 ++++- .../kmath/prob/FactorizedDistribution.kt | 2 +- .../kscience/kmath/prob/RandomGenerator.kt | 2 + .../kscience/kmath/prob/SamplerAlgebra.kt | 17 ++-- .../kmath/prob/internal/InternalGamma.kt | 31 +++---- .../kmath/prob/internal/InternalUtils.kt | 24 ++---- .../samplers/AliasMethodDiscreteSampler.kt | 4 +- .../kmath/prob/samplers/InternalGamma.kt | 2 - .../kmath/prob/samplers/InternalUtils.kt | 2 - .../ZigguratNormalizedGaussianSampler.kt | 43 ++++------ .../kmath/prob/RandomSourceGenerator.kt | 83 ++++++++++++++++++- .../kotlin/kscience/kmath/prob/SamplerTest.kt | 7 +- 22 files changed, 194 insertions(+), 127 deletions(-) delete mode 100644 kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalGamma.kt delete mode 100644 kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalUtils.kt diff --git a/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt index 51fd4f956..c8c5d7b56 100644 --- a/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/structures/StructureReadBenchmark.kt @@ -31,4 +31,4 @@ fun main() { strides.indices().forEach { res = array[strides.offset(it)] } } println("Array reading finished in $time3 millis") -} \ No newline at end of file +} diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index b56151abe..79cfce1f7 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,3 +1,5 @@ +import ru.mipt.npm.gradle.Maturity + plugins { id("ru.mipt.npm.mpp") id("ru.mipt.npm.native") @@ -11,36 +13,42 @@ kotlin.sourceSets.commonMain { readme { description = "Core classes, algebra definitions, basic linear algebra" - maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT + maturity = Maturity.DEVELOPMENT propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + feature( id = "algebras", description = "Algebraic structures: contexts and elements", ref = "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt" ) + feature( id = "nd", description = "Many-dimensional structures", ref = "src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt" ) + feature( id = "buffers", description = "One-dimensional structure", ref = "src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt" ) + feature( id = "expressions", description = "Functional Expressions", ref = "src/commonMain/kotlin/kscience/kmath/expressions" ) + feature( id = "domains", description = "Domains", ref = "src/commonMain/kotlin/kscience/kmath/domains" ) + feature( id = "autodif", description = "Automatic differentiation", ref = "src/commonMain/kotlin/kscience/kmath/misc/AutoDiff.kt" ) -} \ No newline at end of file +} diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt index 20f289596..7af207edc 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/operations/BigInt.kt @@ -237,18 +237,18 @@ public class BigInt internal constructor( ) private fun compareMagnitudes(mag1: Magnitude, mag2: Magnitude): Int { - when { - mag1.size > mag2.size -> return 1 - mag1.size < mag2.size -> return -1 + return when { + mag1.size > mag2.size -> 1 + mag1.size < mag2.size -> -1 + else -> { - for (i in mag1.size - 1 downTo 0) { - if (mag1[i] > mag2[i]) { - return 1 - } else if (mag1[i] < mag2[i]) { - return -1 - } + for (i in mag1.size - 1 downTo 0) return when { + mag1[i] > mag2[i] -> 1 + mag1[i] < mag2[i] -> -1 + else -> continue } - return 0 + + 0 } } } @@ -298,10 +298,11 @@ public class BigInt internal constructor( var carry = 0uL for (i in mag.indices) { - val cur: ULong = carry + mag[i].toULong() * x.toULong() + val cur = carry + mag[i].toULong() * x.toULong() result[i] = (cur and BASE).toUInt() carry = cur shr BASE_SIZE } + result[resultLength - 1] = (carry and BASE).toUInt() return stripLeadingZeros(result) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt index 5174eb314..1806e3559 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt @@ -71,7 +71,7 @@ public interface Buffer { @Suppress("UNCHECKED_CAST") public inline fun auto(type: KClass, size: Int, initializer: (Int) -> T): Buffer = when (type) { - Double::class -> RealBuffer(size) { initializer(it) as Double } as Buffer + Double::class -> real(size) { initializer(it) as Double } as Buffer Short::class -> ShortBuffer(size) { initializer(it) as Short } as Buffer Int::class -> IntBuffer(size) { initializer(it) as Int } as Buffer Long::class -> LongBuffer(size) { initializer(it) as Long } as Buffer diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt index 25fdf3f3d..99c1de9bf 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Structure2D.kt @@ -22,7 +22,7 @@ public interface Structure2D : NDStructure { override fun elements(): Sequence> = sequence { for (i in (0 until rowNum)) - for (j in (0 until colNum)) yield(intArrayOf(i, j) to get(i, j)) + for (j in (0 until colNum)) yield(intArrayOf(i, j) to this@Structure2D[i, j]) } public companion object @@ -35,7 +35,6 @@ private inline class Structure2DWrapper(val structure: NDStructure) : Stru override val shape: IntArray get() = structure.shape override operator fun get(i: Int, j: Int): T = structure[i, j] - override fun elements(): Sequence> = structure.elements() } diff --git a/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NumberNDFieldTest.kt index f5e008ef3..4320821e6 100644 --- a/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/kscience/kmath/structures/NumberNDFieldTest.kt @@ -29,12 +29,11 @@ class NumberNDFieldTest { val array = real2D(3, 3) { i, j -> (i * 10 + j).toDouble() } - for (i in 0..2) { + for (i in 0..2) for (j in 0..2) { val expected = (i * 10 + j).toDouble() assertEquals(expected, array[i, j], "Error at index [$i, $j]") } - } } @Test diff --git a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/Chain.kt index 8c15e52c7..9b9f3e509 100644 --- a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/Chain.kt @@ -63,12 +63,10 @@ public class MarkovChain(private val seed: suspend () -> R, private public fun value(): R? = value - public override suspend fun next(): R { - mutex.withLock { - val newValue = gen(value ?: seed()) - value = newValue - return newValue - } + public override suspend fun next(): R = mutex.withLock { + val newValue = gen(value ?: seed()) + value = newValue + newValue } public override fun fork(): Chain = MarkovChain(seed = { value ?: seed() }, gen = gen) @@ -90,12 +88,10 @@ public class StatefulChain( public fun value(): R? = value - public override suspend fun next(): R { - mutex.withLock { - val newValue = state.gen(value ?: state.seed()) - value = newValue - return newValue - } + public override suspend fun next(): R = mutex.withLock { + val newValue = state.gen(value ?: state.seed()) + value = newValue + newValue } public override fun fork(): Chain = StatefulChain(forkState(state), seed, forkState, gen) diff --git a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/BufferFlow.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/BufferFlow.kt index 328a7807c..7be86b6e7 100644 --- a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/BufferFlow.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/BufferFlow.kt @@ -28,7 +28,7 @@ public fun Flow.chunked(bufferSize: Int, bufferFactory: BufferFactory) var counter = 0 this@chunked.collect { element -> - list.add(element) + list += element counter++ if (counter == bufferSize) { diff --git a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/RingBuffer.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/RingBuffer.kt index 385bbaae2..a59979238 100644 --- a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/RingBuffer.kt +++ b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/streaming/RingBuffer.kt @@ -48,11 +48,9 @@ public class RingBuffer( /** * A safe snapshot operation */ - public suspend fun snapshot(): Buffer { - mutex.withLock { - val copy = buffer.copy() - return VirtualBuffer(size) { i -> copy[startIndex.forward(i)] as T } - } + public suspend fun snapshot(): Buffer = mutex.withLock { + val copy = buffer.copy() + VirtualBuffer(size) { i -> copy[startIndex.forward(i)] as T } } public suspend fun push(element: T) { diff --git a/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt index a8c020c05..6dab9820d 100644 --- a/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt @@ -23,8 +23,8 @@ public class OrderedPiecewisePolynomial>(delimiter: T) : */ public fun putRight(right: T, piece: Polynomial) { require(right > delimiters.last()) { "New delimiter should be to the right of old one" } - delimiters.add(right) - pieces.add(piece) + delimiters += right + pieces += piece } public fun putLeft(left: T, piece: Polynomial) { @@ -52,4 +52,4 @@ public class OrderedPiecewisePolynomial>(delimiter: T) : public fun , C : Ring> PiecewisePolynomial.value(ring: C, arg: T): T? = findPiece(arg)?.value(ring, arg) -public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { value(ring, it) } \ No newline at end of file +public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { value(ring, it) } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt index bbb1de1e3..6c64fb6f5 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt @@ -5,8 +5,18 @@ import kscience.kmath.chains.Chain import kscience.kmath.chains.collect import kscience.kmath.structures.Buffer import kscience.kmath.structures.BufferFactory +import kscience.kmath.structures.IntBuffer +/** + * Sampler that generates chains of values of type [T]. + */ public fun interface Sampler { + /** + * Generates a chain of samples. + * + * @param generator the randomness provider. + * @return the new chain. + */ public fun sample(generator: RandomGenerator): Chain } @@ -59,16 +69,25 @@ public fun Sampler.sampleBuffer( //clear list from previous run tmp.clear() //Fill list - repeat(size) { tmp.add(chain.next()) } + repeat(size) { tmp += chain.next() } //return new buffer with elements from tmp bufferFactory(size) { tmp[it] } } } +/** + * Samples one value from this [Sampler]. + */ public suspend fun Sampler.next(generator: RandomGenerator): T = sample(generator).first() /** - * Generate a bunch of samples from real distributions + * Generates [size] real samples and chunks them into some buffers. */ public fun Sampler.sampleBuffer(generator: RandomGenerator, size: Int): Chain> = sampleBuffer(generator, size, Buffer.Companion::real) + +/** + * Generates [size] integer samples and chunks them into some buffers. + */ +public fun Sampler.sampleBuffer(generator: RandomGenerator, size: Int): Chain> = + sampleBuffer(generator, size, ::IntBuffer) diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt index 128b284be..cc1f0efab 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/FactorizedDistribution.kt @@ -38,6 +38,6 @@ public class DistributionBuilder { private val distributions = ArrayList>() public infix fun String.to(distribution: Distribution) { - distributions.add(NamedDistributionWrapper(this, distribution)) + distributions += NamedDistributionWrapper(this, distribution) } } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt index 2dd4ce51e..ec660fe46 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/RandomGenerator.kt @@ -82,6 +82,8 @@ public interface RandomGenerator { /** * Implements [RandomGenerator] by delegating all operations to [Random]. + * + * @property random the underlying [Random] object. */ public inline class DefaultGenerator(public val random: Random = Random) : RandomGenerator { public override fun nextBoolean(): Boolean = random.nextBoolean() diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/SamplerAlgebra.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/SamplerAlgebra.kt index e363ba30b..7660f2ea0 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/SamplerAlgebra.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/SamplerAlgebra.kt @@ -7,25 +7,28 @@ import kscience.kmath.chains.zip import kscience.kmath.operations.Space import kscience.kmath.operations.invoke -public class BasicSampler(public val chainBuilder: (RandomGenerator) -> Chain) : Sampler { - public override fun sample(generator: RandomGenerator): Chain = chainBuilder(generator) -} - +/** + * Implements [Sampler] by sampling only certain [value]. + * + * @property value the value to sample. + */ public class ConstantSampler(public val value: T) : Sampler { public override fun sample(generator: RandomGenerator): Chain = ConstantChain(value) } /** - * A space for samplers. Allows to perform simple operations on distributions + * A space of samplers. Allows to perform simple operations on distributions. + * + * @property space the space to provide addition and scalar multiplication for [T]. */ public class SamplerSpace(public val space: Space) : Space> { public override val zero: Sampler = ConstantSampler(space.zero) - public override fun add(a: Sampler, b: Sampler): Sampler = BasicSampler { generator -> + public override fun add(a: Sampler, b: Sampler): Sampler = Sampler { generator -> a.sample(generator).zip(b.sample(generator)) { aValue, bValue -> space { aValue + bValue } } } - public override fun multiply(a: Sampler, k: Number): Sampler = BasicSampler { generator -> + public override fun multiply(a: Sampler, k: Number): Sampler = Sampler { generator -> a.sample(generator).map { space { it * k.toDouble() } } } } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalGamma.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalGamma.kt index 7480d2396..8a73659db 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalGamma.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalGamma.kt @@ -98,28 +98,21 @@ internal object InternalGamma { private const val INV_GAMMA1P_M1_C12 = .113302723198169588237412962033074E-05 private const val INV_GAMMA1P_M1_C13 = -.205633841697760710345015413002057E-06 - fun logGamma(x: Double): Double { - val ret: Double + fun logGamma(x: Double): Double = when { + x.isNaN() || x <= 0.0 -> Double.NaN + x < 0.5 -> logGamma1p(x) - ln(x) + x <= 2.5 -> logGamma1p(x - 0.5 - 0.5) - when { - x.isNaN() || x <= 0.0 -> ret = Double.NaN - x < 0.5 -> return logGamma1p(x) - ln(x) - x <= 2.5 -> return logGamma1p(x - 0.5 - 0.5) - - x <= 8.0 -> { - val n = floor(x - 1.5).toInt() - var prod = 1.0 - (1..n).forEach { i -> prod *= x - i } - return logGamma1p(x - (n + 1)) + ln(prod) - } - - else -> { - val tmp = x + LANCZOS_G + .5 - ret = (x + .5) * ln(tmp) - tmp + HALF_LOG_2_PI + ln(lanczos(x) / x) - } + x <= 8.0 -> { + val n = floor(x - 1.5).toInt() + val prod = (1..n).fold(1.0, { prod, i -> prod * (x - i) }) + logGamma1p(x - (n + 1)) + ln(prod) } - return ret + else -> { + val tmp = x + LANCZOS_G + .5 + (x + .5) * ln(tmp) - tmp + HALF_LOG_2_PI + ln(lanczos(x) / x) + } } private fun regularizedGammaP( diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalUtils.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalUtils.kt index 655e284c0..837c9796c 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalUtils.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/internal/InternalUtils.kt @@ -20,24 +20,17 @@ internal object InternalUtils { fun validateProbabilities(probabilities: DoubleArray?): Double { require(!(probabilities == null || probabilities.isEmpty())) { "Probabilities must not be empty." } - var sumProb = 0.0 - probabilities.forEach { prob -> - validateProbability(prob) - sumProb += prob + val sumProb = probabilities.sumByDouble { prob -> + require(!(prob < 0 || prob.isInfinite() || prob.isNaN())) { "Invalid probability: $prob" } + prob } require(!(sumProb.isInfinite() || sumProb <= 0)) { "Invalid sum of probabilities: $sumProb" } return sumProb } - private fun validateProbability(probability: Double): Unit = - require(!(probability < 0 || probability.isInfinite() || probability.isNaN())) { "Invalid probability: $probability" } - - class FactorialLog private constructor( - numValues: Int, - cache: DoubleArray? - ) { + class FactorialLog private constructor(numValues: Int, cache: DoubleArray?) { private val logFactorials: DoubleArray = DoubleArray(numValues) init { @@ -46,14 +39,15 @@ internal object InternalUtils { if (cache != null && cache.size > BEGIN_LOG_FACTORIALS) { // Copy available values. endCopy = min(cache.size, numValues) + cache.copyInto( logFactorials, BEGIN_LOG_FACTORIALS, BEGIN_LOG_FACTORIALS, endCopy ) - } + } else // All values to be computed - else endCopy = BEGIN_LOG_FACTORIALS + endCopy = BEGIN_LOG_FACTORIALS // Compute remaining values. (endCopy until numValues).forEach { i -> @@ -65,9 +59,7 @@ internal object InternalUtils { } fun value(n: Int): Double { - if (n < logFactorials.size) - return logFactorials[n] - + if (n < logFactorials.size) return logFactorials[n] return if (n < FACTORIALS.size) ln(FACTORIALS[n].toDouble()) else InternalGamma.logGamma(n + 1.0) } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AliasMethodDiscreteSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AliasMethodDiscreteSampler.kt index f04b5bcb0..db78a41a8 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AliasMethodDiscreteSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/AliasMethodDiscreteSampler.kt @@ -42,7 +42,7 @@ public open class AliasMethodDiscreteSampler private constructor( protected val alias: IntArray ) : Sampler { - private class SmallTableAliasMethodDiscreteSampler internal constructor( + private class SmallTableAliasMethodDiscreteSampler( probability: LongArray, alias: IntArray ) : AliasMethodDiscreteSampler(probability, alias) { @@ -71,7 +71,7 @@ public open class AliasMethodDiscreteSampler private constructor( } } - override fun sample(generator: RandomGenerator): Chain = generator.chain { + public override fun sample(generator: RandomGenerator): Chain = generator.chain { // This implements the algorithm as per Vose (1991): // v = uniform() in [0, 1) // j = uniform(n) in [0, n) diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalGamma.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalGamma.kt deleted file mode 100644 index d970d1447..000000000 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalGamma.kt +++ /dev/null @@ -1,2 +0,0 @@ -package kscience.kmath.prob.samplers - diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalUtils.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalUtils.kt deleted file mode 100644 index d970d1447..000000000 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/InternalUtils.kt +++ /dev/null @@ -1,2 +0,0 @@ -package kscience.kmath.prob.samplers - diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt index c9103ba86..60407e604 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/samplers/ZigguratNormalizedGaussianSampler.kt @@ -26,35 +26,24 @@ public class ZigguratNormalizedGaussianSampler private constructor() : public override fun sample(generator: RandomGenerator): Chain = generator.chain { sampleOne(this) } public override fun toString(): String = "Ziggurat normalized Gaussian deviate" - private fun fix( - generator: RandomGenerator, - hz: Long, - iz: Int - ): Double { - var x: Double - var y: Double - x = hz * W[iz] + private fun fix(generator: RandomGenerator, hz: Long, iz: Int): Double { + var x = hz * W[iz] - return if (iz == 0) { - // Base strip. - // This branch is called about 5.7624515E-4 times per sample. - do { - y = -ln(generator.nextDouble()) - x = -ln(generator.nextDouble()) * ONE_OVER_R - } while (y + y < x * x) + return when { + iz == 0 -> { + var y: Double - val out = R + x - if (hz > 0) out else -out - } else { - // Wedge of other strips. - // This branch is called about 0.027323 times per sample. - // else - // Try again. - // This branch is called about 0.012362 times per sample. - if (F[iz] + generator.nextDouble() * (F[iz - 1] - F[iz]) < gauss( - x - ) - ) x else sampleOne(generator) + do { + y = -ln(generator.nextDouble()) + x = -ln(generator.nextDouble()) * ONE_OVER_R + } while (y + y < x * x) + + val out = R + x + if (hz > 0) out else -out + } + + F[iz] + generator.nextDouble() * (F[iz - 1] - F[iz]) < gauss(x) -> x + else -> sampleOne(generator) } } diff --git a/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt b/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt index 9cdde6b4b..e6a7ac1f1 100644 --- a/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt +++ b/kmath-prob/src/jvmMain/kotlin/kscience/kmath/prob/RandomSourceGenerator.kt @@ -3,10 +3,14 @@ package kscience.kmath.prob import org.apache.commons.rng.UniformRandomProvider import org.apache.commons.rng.simple.RandomSource -public class RandomSourceGenerator(public val source: RandomSource, seed: Long?) : RandomGenerator { - internal val random: UniformRandomProvider = seed?.let { - RandomSource.create(source, seed) - } ?: RandomSource.create(source) +/** + * Implements [RandomGenerator] by delegating all operations to [RandomSource]. + * + * @property source the underlying [RandomSource] object. + */ +public class RandomSourceGenerator internal constructor(public val source: RandomSource, seed: Long?) : RandomGenerator { + internal val random: UniformRandomProvider = seed?.let { RandomSource.create(source, seed) } + ?: RandomSource.create(source) public override fun nextBoolean(): Boolean = random.nextBoolean() public override fun nextDouble(): Double = random.nextDouble() @@ -23,19 +27,84 @@ public class RandomSourceGenerator(public val source: RandomSource, seed: Long?) public override fun fork(): RandomGenerator = RandomSourceGenerator(source, nextLong()) } +/** + * Implements [UniformRandomProvider] by delegating all operations to [RandomGenerator]. + * + * @property generator the underlying [RandomGenerator] object. + */ public inline class RandomGeneratorProvider(public val generator: RandomGenerator) : UniformRandomProvider { + /** + * Generates a [Boolean] value. + * + * @return the next random value. + */ public override fun nextBoolean(): Boolean = generator.nextBoolean() + + /** + * Generates a [Float] value between 0 and 1. + * + * @return the next random value between 0 and 1. + */ public override fun nextFloat(): Float = generator.nextDouble().toFloat() + + /** + * Generates [Byte] values and places them into a user-supplied array. + * + * The number of random bytes produced is equal to the length of the the byte array. + * + * @param bytes byte array in which to put the random bytes. + */ public override fun nextBytes(bytes: ByteArray): Unit = generator.fillBytes(bytes) + /** + * Generates [Byte] values and places them into a user-supplied array. + * + * The array is filled with bytes extracted from random integers. This implies that the number of random bytes + * generated may be larger than the length of the byte array. + * + * @param bytes the array in which to put the generated bytes. + * @param start the index at which to start inserting the generated bytes. + * @param len the number of bytes to insert. + */ public override fun nextBytes(bytes: ByteArray, start: Int, len: Int) { generator.fillBytes(bytes, start, start + len) } + /** + * Generates an [Int] value. + * + * @return the next random value. + */ public override fun nextInt(): Int = generator.nextInt() + + /** + * Generates an [Int] value between 0 (inclusive) and the specified value (exclusive). + * + * @param n the bound on the random number to be returned. Must be positive. + * @return a random integer between 0 (inclusive) and [n] (exclusive). + */ public override fun nextInt(n: Int): Int = generator.nextInt(n) + + /** + * Generates a [Double] value between 0 and 1. + * + * @return the next random value between 0 and 1. + */ public override fun nextDouble(): Double = generator.nextDouble() + + /** + * Generates a [Long] value. + * + * @return the next random value. + */ public override fun nextLong(): Long = generator.nextLong() + + /** + * Generates a [Long] value between 0 (inclusive) and the specified value (exclusive). + * + * @param n Bound on the random number to be returned. Must be positive. + * @return a random long value between 0 (inclusive) and [n] (exclusive). + */ public override fun nextLong(n: Long): Long = generator.nextLong(n) } @@ -48,8 +117,14 @@ public fun RandomGenerator.asUniformRandomProvider(): UniformRandomProvider = if else RandomGeneratorProvider(this) +/** + * Returns [RandomSourceGenerator] with given [RandomSource] and [seed]. + */ public fun RandomGenerator.Companion.fromSource(source: RandomSource, seed: Long? = null): RandomSourceGenerator = RandomSourceGenerator(source, seed) +/** + * Returns [RandomSourceGenerator] with [RandomSource.MT] algorithm and given [seed]. + */ public fun RandomGenerator.Companion.mersenneTwister(seed: Long? = null): RandomSourceGenerator = fromSource(RandomSource.MT, seed) diff --git a/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt b/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt index 75db5c402..0ca5a8aeb 100644 --- a/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt +++ b/kmath-prob/src/jvmTest/kotlin/kscience/kmath/prob/SamplerTest.kt @@ -7,11 +7,8 @@ class SamplerTest { @Test fun bufferSamplerTest() { - val sampler: Sampler = - BasicSampler { it.chain { nextDouble() } } + val sampler = Sampler { it.chain { nextDouble() } } val data = sampler.sampleBuffer(RandomGenerator.default, 100) - runBlocking { - println(data.next()) - } + runBlocking { println(data.next()) } } } \ No newline at end of file From 59b120e0861432b77fa9096fc8d662c2680e593f Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 23 Oct 2020 17:01:16 +0700 Subject: [PATCH 018/393] Fix platform declarations --- .../src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt index 6c64fb6f5..1b2681703 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/Distribution.kt @@ -6,6 +6,7 @@ import kscience.kmath.chains.collect import kscience.kmath.structures.Buffer import kscience.kmath.structures.BufferFactory import kscience.kmath.structures.IntBuffer +import kotlin.jvm.JvmName /** * Sampler that generates chains of values of type [T]. @@ -83,11 +84,13 @@ public suspend fun Sampler.next(generator: RandomGenerator): T = sa /** * Generates [size] real samples and chunks them into some buffers. */ +@JvmName("sampleRealBuffer") public fun Sampler.sampleBuffer(generator: RandomGenerator, size: Int): Chain> = sampleBuffer(generator, size, Buffer.Companion::real) /** * Generates [size] integer samples and chunks them into some buffers. */ +@JvmName("sampleIntBuffer") public fun Sampler.sampleBuffer(generator: RandomGenerator, size: Int): Chain> = sampleBuffer(generator, size, ::IntBuffer) From 55909aee0d1c929c239a4f837409e2c722c1790f Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 28 Oct 2020 18:36:00 +0700 Subject: [PATCH 019/393] Add additional constructor --- .../kotlin/kscience/kmath/structures/ViktorBenchmark.kt | 2 +- .../kmath/prob/distributions/NormalDistribution.kt | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt index 464925ca0..df35b0b78 100644 --- a/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt +++ b/examples/src/benchmarks/kotlin/kscience/kmath/structures/ViktorBenchmark.kt @@ -36,7 +36,7 @@ internal class ViktorBenchmark { @Benchmark fun rawViktor() { - val one = F64Array.full(init = 1.0, shape = *intArrayOf(dim, dim)) + val one = F64Array.full(init = 1.0, shape = intArrayOf(dim, dim)) var res = one repeat(n) { res = res + one } } diff --git a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/distributions/NormalDistribution.kt b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/distributions/NormalDistribution.kt index 095ac5ea9..57c39018d 100644 --- a/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/distributions/NormalDistribution.kt +++ b/kmath-prob/src/commonMain/kotlin/kscience/kmath/prob/distributions/NormalDistribution.kt @@ -5,9 +5,17 @@ import kscience.kmath.prob.RandomGenerator import kscience.kmath.prob.UnivariateDistribution import kscience.kmath.prob.internal.InternalErf import kscience.kmath.prob.samplers.GaussianSampler +import kscience.kmath.prob.samplers.NormalizedGaussianSampler +import kscience.kmath.prob.samplers.ZigguratNormalizedGaussianSampler import kotlin.math.* public inline class NormalDistribution(public val sampler: GaussianSampler) : UnivariateDistribution { + public constructor( + mean: Double, + standardDeviation: Double, + normalized: NormalizedGaussianSampler = ZigguratNormalizedGaussianSampler.of(), + ) : this(GaussianSampler.of(mean, standardDeviation, normalized)) + public override fun probability(arg: Double): Double { val x1 = (arg - sampler.mean) / sampler.standardDeviation return exp(-0.5 * x1 * x1 - (ln(sampler.standardDeviation) + 0.5 * ln(2 * PI))) From f18cd9ad40e2e3b9ef0365c743d059267eab0b3a Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 29 Nov 2020 16:25:08 +0700 Subject: [PATCH 020/393] Fix package names --- .../kmath/commons/prob/DistributionBenchmark.kt | 8 ++++---- .../kmath/commons/prob/DistributionDemo.kt | 4 ++-- .../kmath/commons/optimization/OptimizeTest.kt | 15 +++++---------- .../stat/distributions/NormalDistribution.kt | 14 +++++++------- .../kscience/kmath/stat/internal/InternalErf.kt | 2 +- .../kscience/kmath/stat/internal/InternalGamma.kt | 2 +- .../kscience/kmath/stat/internal/InternalUtils.kt | 2 +- .../samplers/AhrensDieterExponentialSampler.kt | 10 +++++----- .../AhrensDieterMarsagliaTsangGammaSampler.kt | 10 +++++----- .../stat/samplers/AliasMethodDiscreteSampler.kt | 10 +++++----- .../BoxMullerNormalizedGaussianSampler.kt | 8 ++++---- .../kmath/stat/samplers/GaussianSampler.kt | 6 +++--- .../stat/samplers/KempSmallMeanPoissonSampler.kt | 8 ++++---- .../stat/samplers/LargeMeanPoissonSampler.kt | 12 ++++++------ .../MarsagliaNormalizedGaussianSampler.kt | 8 ++++---- .../stat/samplers/NormalizedGaussianSampler.kt | 4 ++-- .../kmath/stat/samplers/PoissonSampler.kt | 6 +++--- .../stat/samplers/SmallMeanPoissonSampler.kt | 8 ++++---- .../samplers/ZigguratNormalizedGaussianSampler.kt | 8 ++++---- .../kmath/stat/CommonsDistributionsTest.kt | 2 +- 20 files changed, 71 insertions(+), 76 deletions(-) diff --git a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt index e4a5bc534..5c7442c1b 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt @@ -3,10 +3,10 @@ package kscience.kmath.commons.prob import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.blocking -import kscience.kmath.prob.fromSource -import kscience.kmath.prob.samplers.GaussianSampler +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.blocking +import kscience.kmath.stat.fromSource +import kscience.kmath.stat.samplers.GaussianSampler import org.apache.commons.rng.simple.RandomSource import java.time.Duration import java.time.Instant diff --git a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt index 7f06f4a1f..c96826ef7 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt +++ b/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt @@ -3,8 +3,8 @@ package kscience.kmath.commons.prob import kotlinx.coroutines.runBlocking import kscience.kmath.chains.Chain import kscience.kmath.chains.collectWithState -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.samplers.ZigguratNormalizedGaussianSampler +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.samplers.ZigguratNormalizedGaussianSampler private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0) diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt index 3290c8f32..184d209d5 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -1,11 +1,11 @@ package kscience.kmath.commons.optimization +import kotlinx.coroutines.runBlocking import kscience.kmath.commons.expressions.DerivativeStructureExpression import kscience.kmath.expressions.symbol -import kscience.kmath.stat.Distribution import kscience.kmath.stat.Fitting import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.normal +import kscience.kmath.stat.distributions.NormalDistribution import org.junit.jupiter.api.Test import kotlin.math.pow @@ -39,20 +39,15 @@ internal class OptimizeTest { } @Test - fun testCmFit() { + fun testCmFit() = runBlocking { val a by symbol val b by symbol val c by symbol - val sigma = 1.0 - val generator = Distribution.normal(0.0, sigma) + val generator = NormalDistribution(0.0, sigma) val chain = generator.sample(RandomGenerator.default(112667)) val x = (1..100).map(Int::toDouble) - - val y = x.map { - it.pow(2) + it + 1 + chain.nextDouble() - } - + val y = x.map { it.pow(2) + it + 1.0 + chain.next() } val yErr = List(x.size) { sigma } val chi2 = Fitting.chiSquared(x, y, yErr) { x1 -> diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/distributions/NormalDistribution.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/distributions/NormalDistribution.kt index 57c39018d..4332d92fe 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/distributions/NormalDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/distributions/NormalDistribution.kt @@ -1,12 +1,12 @@ -package kscience.kmath.prob.distributions +package kscience.kmath.stat.distributions import kscience.kmath.chains.Chain -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.UnivariateDistribution -import kscience.kmath.prob.internal.InternalErf -import kscience.kmath.prob.samplers.GaussianSampler -import kscience.kmath.prob.samplers.NormalizedGaussianSampler -import kscience.kmath.prob.samplers.ZigguratNormalizedGaussianSampler +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.UnivariateDistribution +import kscience.kmath.stat.internal.InternalErf +import kscience.kmath.stat.samplers.GaussianSampler +import kscience.kmath.stat.samplers.NormalizedGaussianSampler +import kscience.kmath.stat.samplers.ZigguratNormalizedGaussianSampler import kotlin.math.* public inline class NormalDistribution(public val sampler: GaussianSampler) : UnivariateDistribution { diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalErf.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalErf.kt index 178423e68..bcc4d1481 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalErf.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalErf.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob.internal +package kscience.kmath.stat.internal import kotlin.math.abs diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalGamma.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalGamma.kt index 8a73659db..dce84712a 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalGamma.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalGamma.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob.internal +package kscience.kmath.stat.internal import kotlin.math.* diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalUtils.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalUtils.kt index 837c9796c..9997eeb57 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalUtils.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalUtils.kt @@ -1,4 +1,4 @@ -package kscience.kmath.prob.internal +package kscience.kmath.stat.internal import kotlin.math.ln import kotlin.math.min diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt index d4b443e9c..cea6de20d 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt @@ -1,10 +1,10 @@ -package kscience.kmath.prob.samplers +package kscience.kmath.stat.samplers import kscience.kmath.chains.Chain -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.Sampler -import kscience.kmath.prob.chain -import kscience.kmath.prob.internal.InternalUtils +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.Sampler +import kscience.kmath.stat.chain +import kscience.kmath.stat.internal.InternalUtils import kotlin.math.ln import kotlin.math.pow diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt index e18a44cb9..f36e34f34 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt @@ -1,10 +1,10 @@ -package kscience.kmath.prob.samplers +package kscience.kmath.stat.samplers import kscience.kmath.chains.Chain -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.Sampler -import kscience.kmath.prob.chain -import kscience.kmath.prob.next +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.Sampler +import kscience.kmath.stat.chain +import kscience.kmath.stat.next import kotlin.math.* /** diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt index db78a41a8..a76fcd543 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt @@ -1,10 +1,10 @@ -package kscience.kmath.prob.samplers +package kscience.kmath.stat.samplers import kscience.kmath.chains.Chain -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.Sampler -import kscience.kmath.prob.chain -import kscience.kmath.prob.internal.InternalUtils +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.Sampler +import kscience.kmath.stat.chain +import kscience.kmath.stat.internal.InternalUtils import kotlin.math.ceil import kotlin.math.max import kotlin.math.min diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt index 50a7b00c2..dc3a9b3e6 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt @@ -1,9 +1,9 @@ -package kscience.kmath.prob.samplers +package kscience.kmath.stat.samplers import kscience.kmath.chains.Chain -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.Sampler -import kscience.kmath.prob.chain +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.Sampler +import kscience.kmath.stat.chain import kotlin.math.* /** diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/GaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/GaussianSampler.kt index 1a5e4cfdd..5e54d2f18 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/GaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/GaussianSampler.kt @@ -1,9 +1,9 @@ -package kscience.kmath.prob.samplers +package kscience.kmath.stat.samplers import kscience.kmath.chains.Chain import kscience.kmath.chains.map -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.Sampler +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.Sampler /** * Sampling from a Gaussian distribution with given mean and standard deviation. diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt index 624fc9a7e..4b04f3e6f 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt @@ -1,9 +1,9 @@ -package kscience.kmath.prob.samplers +package kscience.kmath.stat.samplers import kscience.kmath.chains.Chain -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.Sampler -import kscience.kmath.prob.chain +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.Sampler +import kscience.kmath.stat.chain import kotlin.math.exp /** diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt index 8a54fabaa..a841d47fc 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt @@ -1,12 +1,12 @@ -package kscience.kmath.prob.samplers +package kscience.kmath.stat.samplers import kscience.kmath.chains.Chain import kscience.kmath.chains.ConstantChain -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.Sampler -import kscience.kmath.prob.chain -import kscience.kmath.prob.internal.InternalUtils -import kscience.kmath.prob.next +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.Sampler +import kscience.kmath.stat.chain +import kscience.kmath.stat.internal.InternalUtils +import kscience.kmath.stat.next import kotlin.math.* /** diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt index 69c04c20b..1696a7701 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt @@ -1,9 +1,9 @@ -package kscience.kmath.prob.samplers +package kscience.kmath.stat.samplers import kscience.kmath.chains.Chain -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.Sampler -import kscience.kmath.prob.chain +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.Sampler +import kscience.kmath.stat.chain import kotlin.math.ln import kotlin.math.sqrt diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt index af2ab876d..8995d3030 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt @@ -1,6 +1,6 @@ -package kscience.kmath.prob.samplers +package kscience.kmath.stat.samplers -import kscience.kmath.prob.Sampler +import kscience.kmath.stat.Sampler /** * Marker interface for a sampler that generates values from an N(0,1) diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/PoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/PoissonSampler.kt index 02d8d5632..415e9c826 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/PoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/PoissonSampler.kt @@ -1,8 +1,8 @@ -package kscience.kmath.prob.samplers +package kscience.kmath.stat.samplers import kscience.kmath.chains.Chain -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.Sampler +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.Sampler /** * Sampler for the Poisson distribution. diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt index ff4233288..61d7e3484 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt @@ -1,9 +1,9 @@ -package kscience.kmath.prob.samplers +package kscience.kmath.stat.samplers import kscience.kmath.chains.Chain -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.Sampler -import kscience.kmath.prob.chain +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.Sampler +import kscience.kmath.stat.chain import kotlin.math.ceil import kotlin.math.exp diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt index 60407e604..c0c9c28e0 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt @@ -1,9 +1,9 @@ -package kscience.kmath.prob.samplers +package kscience.kmath.stat.samplers import kscience.kmath.chains.Chain -import kscience.kmath.prob.RandomGenerator -import kscience.kmath.prob.Sampler -import kscience.kmath.prob.chain +import kscience.kmath.stat.RandomGenerator +import kscience.kmath.stat.Sampler +import kscience.kmath.stat.chain import kotlin.math.* /** diff --git a/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/CommonsDistributionsTest.kt index 63cb33f7b..8090f9b2b 100644 --- a/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -3,7 +3,7 @@ package kscience.kmath.stat import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.toList import kotlinx.coroutines.runBlocking -import kscience.kmath.prob.samplers.GaussianSampler +import kscience.kmath.stat.samplers.GaussianSampler import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test From 5a3fccb455667f98996b2ec7aeb4116a4465abe2 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 29 Nov 2020 22:02:06 +0700 Subject: [PATCH 021/393] Add reference to Commons Math implementation of InternalErf, fix markdown issues, rename prob package in examples to stat --- .../kmath/{commons/prob => stat}/DistributionBenchmark.kt | 5 +---- .../kmath/{commons/prob => stat}/DistributionDemo.kt | 2 +- .../kscience/kmath/stat/distributions/NormalDistribution.kt | 3 +++ .../kotlin/kscience/kmath/stat/internal/InternalErf.kt | 4 ++++ .../kmath/stat/samplers/AhrensDieterExponentialSampler.kt | 2 +- .../stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt | 3 ++- .../kmath/stat/samplers/AliasMethodDiscreteSampler.kt | 2 +- .../stat/samplers/BoxMullerNormalizedGaussianSampler.kt | 2 +- .../kotlin/kscience/kmath/stat/samplers/GaussianSampler.kt | 2 +- .../kmath/stat/samplers/KempSmallMeanPoissonSampler.kt | 2 +- .../kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt | 2 +- .../stat/samplers/MarsagliaNormalizedGaussianSampler.kt | 2 +- .../kotlin/kscience/kmath/stat/samplers/PoissonSampler.kt | 2 +- .../kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt | 2 +- .../kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt | 2 +- 15 files changed, 21 insertions(+), 16 deletions(-) rename examples/src/main/kotlin/kscience/kmath/{commons/prob => stat}/DistributionBenchmark.kt (93%) rename examples/src/main/kotlin/kscience/kmath/{commons/prob => stat}/DistributionDemo.kt (96%) diff --git a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt similarity index 93% rename from examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt rename to examples/src/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt index 5c7442c1b..4478903d9 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt @@ -1,11 +1,8 @@ -package kscience.kmath.commons.prob +package kscience.kmath.stat import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.blocking -import kscience.kmath.stat.fromSource import kscience.kmath.stat.samplers.GaussianSampler import org.apache.commons.rng.simple.RandomSource import java.time.Duration diff --git a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt b/examples/src/main/kotlin/kscience/kmath/stat/DistributionDemo.kt similarity index 96% rename from examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt rename to examples/src/main/kotlin/kscience/kmath/stat/DistributionDemo.kt index c96826ef7..6bc72215e 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/prob/DistributionDemo.kt +++ b/examples/src/main/kotlin/kscience/kmath/stat/DistributionDemo.kt @@ -1,4 +1,4 @@ -package kscience.kmath.commons.prob +package kscience.kmath.stat import kotlinx.coroutines.runBlocking import kscience.kmath.chains.Chain diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/distributions/NormalDistribution.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/distributions/NormalDistribution.kt index 4332d92fe..9059a0038 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/distributions/NormalDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/distributions/NormalDistribution.kt @@ -9,6 +9,9 @@ import kscience.kmath.stat.samplers.NormalizedGaussianSampler import kscience.kmath.stat.samplers.ZigguratNormalizedGaussianSampler import kotlin.math.* +/** + * Implements [UnivariateDistribution] for the normal (gaussian) distribution. + */ public inline class NormalDistribution(public val sampler: GaussianSampler) : UnivariateDistribution { public constructor( mean: Double, diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalErf.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalErf.kt index bcc4d1481..04eb3ef0e 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalErf.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalErf.kt @@ -2,6 +2,10 @@ package kscience.kmath.stat.internal import kotlin.math.abs +/** + * Based on Commons Math implementation. + * See [https://commons.apache.org/proper/commons-math/javadocs/api-3.3/org/apache/commons/math3/special/Erf.html]. + */ internal object InternalErf { fun erfc(x: Double): Double { if (abs(x) > 40) return if (x > 0) 0.0 else 2.0 diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt index cea6de20d..853e952bb 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt @@ -12,7 +12,7 @@ import kotlin.math.pow * Sampling from an [exponential distribution](http://mathworld.wolfram.com/ExponentialDistribution.html). * * Based on Commons RNG implementation. - * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.html + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.html]. */ public class AhrensDieterExponentialSampler private constructor(public val mean: Double) : Sampler { public override fun sample(generator: RandomGenerator): Chain = generator.chain { diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt index f36e34f34..98cb83332 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt @@ -15,7 +15,8 @@ import kotlin.math.* * Marsaglia and Tsang, A Simple Method for Generating Gamma Variables. ACM Transactions on Mathematical Software, Volume 26 Issue 3, September, 2000. * * Based on Commons RNG implementation. - * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterMarsagliaTsangGammaSampler.html + * + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterMarsagliaTsangGammaSampler.html]. */ public class AhrensDieterMarsagliaTsangGammaSampler private constructor( alpha: Double, diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt index a76fcd543..a4dc537b5 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt @@ -34,7 +34,7 @@ import kotlin.math.min * that exploit the power of 2. * * Based on Commons RNG implementation. - * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AliasMethodDiscreteSampler.html + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AliasMethodDiscreteSampler.html]. */ public open class AliasMethodDiscreteSampler private constructor( // Deliberate direct storage of input arrays diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt index dc3a9b3e6..20412f64b 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt @@ -11,7 +11,7 @@ import kotlin.math.* * distribution. * * Based on Commons RNG implementation. - * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.html + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.html]. */ public class BoxMullerNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { private var nextGaussian: Double = Double.NaN diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/GaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/GaussianSampler.kt index 5e54d2f18..92dd27d02 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/GaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/GaussianSampler.kt @@ -9,7 +9,7 @@ import kscience.kmath.stat.Sampler * Sampling from a Gaussian distribution with given mean and standard deviation. * * Based on Commons RNG implementation. - * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/GaussianSampler.html + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/GaussianSampler.html]. * * @property mean the mean of the distribution. * @property standardDeviation the variance of the distribution. diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt index 4b04f3e6f..78da230ca 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt @@ -16,7 +16,7 @@ import kotlin.math.exp * Sampling uses 1 call to UniformRandomProvider.nextDouble(). This method provides an alternative to the SmallMeanPoissonSampler for slow generators of double. * * Based on Commons RNG implementation. - * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.html + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.html]. */ public class KempSmallMeanPoissonSampler private constructor( private val p0: Double, diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt index a841d47fc..c880d7a20 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt @@ -18,7 +18,7 @@ import kotlin.math.* * This sampler is suitable for mean >= 40. * * Based on Commons RNG implementation. - * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/LargeMeanPoissonSampler.html + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/LargeMeanPoissonSampler.html]. */ public class LargeMeanPoissonSampler private constructor(public val mean: Double) : Sampler { private val exponential: Sampler = AhrensDieterExponentialSampler.of(1.0) diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt index 1696a7701..8077f9f75 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt @@ -13,7 +13,7 @@ import kotlin.math.sqrt * [BoxMullerNormalizedGaussianSampler]. * * Based on Commons RNG implementation. - * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.html + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.html] */ public class MarsagliaNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { private var nextGaussian = Double.NaN diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/PoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/PoissonSampler.kt index 415e9c826..e9a6244a6 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/PoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/PoissonSampler.kt @@ -14,7 +14,7 @@ import kscience.kmath.stat.Sampler * Devroye, Luc. (1981). The Computer Generation of Poisson Random Variables Computing vol. 26 pp. 197-207. * * Based on Commons RNG implementation. - * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/PoissonSampler.html + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/PoissonSampler.html]. */ public class PoissonSampler private constructor(mean: Double) : Sampler { private val poissonSamplerDelegate: Sampler = of(mean) diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt index 61d7e3484..e9ce8a6a6 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt @@ -17,7 +17,7 @@ import kotlin.math.exp * * Based on Commons RNG implementation. * - * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/SmallMeanPoissonSampler.html + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/SmallMeanPoissonSampler.html]. */ public class SmallMeanPoissonSampler private constructor(mean: Double) : Sampler { private val p0: Double = exp(-mean) diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt index c0c9c28e0..e9e8d91da 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt @@ -12,7 +12,7 @@ import kotlin.math.* * implementation has been adapted from the C code provided therein. * * Based on Commons RNG implementation. - * See https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.html + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.html]. */ public class ZigguratNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { From e43aad33fe26d14758940f70d98457e59252cb15 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 12 Dec 2020 17:13:14 +0700 Subject: [PATCH 022/393] Add missing import --- .../src/main/kotlin/kscience/kmath/stat/DistributionDemo.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/src/main/kotlin/kscience/kmath/stat/DistributionDemo.kt b/examples/src/main/kotlin/kscience/kmath/stat/DistributionDemo.kt index 8562c15df..dd04c12e5 100644 --- a/examples/src/main/kotlin/kscience/kmath/stat/DistributionDemo.kt +++ b/examples/src/main/kotlin/kscience/kmath/stat/DistributionDemo.kt @@ -3,6 +3,7 @@ package kscience.kmath.stat import kotlinx.coroutines.runBlocking import kscience.kmath.chains.Chain import kscience.kmath.chains.collectWithState +import kscience.kmath.stat.distributions.NormalDistribution /** * The state of distribution averager. @@ -21,7 +22,7 @@ private fun Chain.mean(): Chain = collectWithState(AveragingChai fun main() { - val normal = NormalDistribution() + val normal = NormalDistribution(0.0, 2.0) val chain = normal.sample(RandomGenerator.default).mean() runBlocking { From 2f116604398fed07a1ccdd50ea2ab20cc297365f Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 12 Dec 2020 21:03:28 +0700 Subject: [PATCH 023/393] Replace Distribution.normal with NormalDistribution --- .../kscience/kmath/commons/fit/fitWithAutoDiff.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/src/main/kotlin/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/kscience/kmath/commons/fit/fitWithAutoDiff.kt index c0cd9dc5c..22d642d92 100644 --- a/examples/src/main/kotlin/kscience/kmath/commons/fit/fitWithAutoDiff.kt +++ b/examples/src/main/kotlin/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -9,6 +9,7 @@ import kscience.kmath.real.RealVector import kscience.kmath.real.map import kscience.kmath.real.step import kscience.kmath.stat.* +import kscience.kmath.stat.distributions.NormalDistribution import kscience.kmath.structures.asIterable import kscience.kmath.structures.toList import kscience.plotly.* @@ -33,10 +34,9 @@ operator fun TraceValues.invoke(vector: RealVector) { /** * Least squares fie with auto-differentiation. Uses `kmath-commons` and `kmath-for-real` modules. */ -fun main() { - +suspend fun main() { //A generator for a normally distributed values - val generator = Distribution.normal() + val generator = NormalDistribution(2.0, 7.0) //A chain/flow of random values with the given seed val chain = generator.sample(RandomGenerator.default(112667)) @@ -49,7 +49,7 @@ fun main() { //Perform an operation on each x value (much more effective, than numpy) val y = x.map { val value = it.pow(2) + it + 1 - value + chain.nextDouble() * sqrt(value) + value + chain.next() * sqrt(value) } // this will also work, but less effective: // val y = x.pow(2)+ x + 1 + chain.nextDouble() @@ -99,4 +99,4 @@ fun main() { } page.makeFile() -} \ No newline at end of file +} From 9c77f8f02f6a5ce98bec2045872c761e37c46bd3 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 24 Jan 2021 01:59:42 +0700 Subject: [PATCH 024/393] Remove incorrect lines --- .../main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/src/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt b/examples/src/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt index 92b6f046d..4478903d9 100644 --- a/examples/src/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/kscience/kmath/stat/DistributionBenchmark.kt @@ -63,6 +63,4 @@ fun main(): Unit = runBlocking(Dispatchers.Default) { val directJob = async { runApacheDirect() } println("KMath Chained: ${chainJob.await()}") println("Apache Direct: ${directJob.await()}") - val normal = GaussianSampler.of(7.0, 2.0) - val chain = normal.sample(generator).blocking() } From 16fcc1c412d61a57a660dbec4b0fab799aad8122 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 21 Feb 2021 16:58:43 +0300 Subject: [PATCH 025/393] Remove bintray badge. --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index e524e1cf3..f598651c4 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,6 @@ ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) -Bintray: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) - -Bintray-dev: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion) - # KMath Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based analog to From aa69c8fde464470c0db9907dafe499621581c9f3 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 27 Feb 2021 09:56:50 +0300 Subject: [PATCH 026/393] Update README.md JS-IR badge --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f598651c4..6f2675425 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ [![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) - ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) +[![Kotlin JS IR supported](https://img.shields.io/badge/Kotlin%2FJS-IR%20supported-yellow)](https://kotl.in/jsirsupported) + # KMath Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based analog to From d0cf16c8a616c338b981c6b7b38935811de1530f Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 28 Feb 2021 17:06:47 +0700 Subject: [PATCH 027/393] Rework GA workflows --- .github/workflows/build.yml | 110 ++++++-------------------------- .github/workflows/deploy.yml | 43 +++++++++++++ .github/workflows/release.yml | 117 ---------------------------------- build.gradle.kts | 15 ++++- gradle.properties | 1 + 5 files changed, 75 insertions(+), 211 deletions(-) create mode 100644 .github/workflows/deploy.yml delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 626062abf..56f8721eb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,107 +1,35 @@ -name: Gradle build - +name: build on: [ push ] jobs: - build-ubuntu: - runs-on: ubuntu-20.04 - + build: + strategy: + matrix: + os: [ macOS-latest, windows-latest ] + runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v2 + - name: Checkout the repo + uses: actions/checkout@v2 - name: Set up JDK 11 uses: actions/setup-java@v1 with: java-version: 11 - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Install Chrome - run: | - sudo apt install -y libappindicator1 fonts-liberation - wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb - sudo dpkg -i google-chrome*.deb - - name: Cache gradle - uses: actions/cache@v2 - with: - path: | - .gradle - build - ~/.gradle - key: gradle - restore-keys: gradle - - - name: Cache konan - uses: actions/cache@v2 - with: - path: | - ~/.konan/dependencies - ~/.konan/kotlin-native-prebuilt-linux-* - key: ${{ runner.os }}-konan - restore-keys: ${{ runner.os }}-konan - - name: Build with Gradle - run: ./gradlew -Dorg.gradle.daemon=false --build-cache build - - build-osx: - runs-on: macos-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Cache gradle - uses: actions/cache@v2 - with: - path: | - .gradle - build - ~/.gradle - key: gradle - restore-keys: gradle - - - name: Cache konan - uses: actions/cache@v2 - with: - path: | - ~/.konan/dependencies - ~/.konan/kotlin-native-prebuilt-macos-* - key: ${{ runner.os }}-konan - restore-keys: ${{ runner.os }}-konan - - name: Build with Gradle - run: sudo ./gradlew -Dorg.gradle.daemon=false --build-cache build - - build-windows: - runs-on: windows-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - - name: Grant execute permission for gradlew - run: chmod +x gradlew - name: Add msys to path + if: matrix.os == 'windows-latest' run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" - name: Cache gradle uses: actions/cache@v2 with: - path: | - .gradle - build - ~/.gradle - key: ${{ runner.os }}-gradle - restore-keys: ${{ runner.os }}-gradle - + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} + restore-keys: | + ${{ runner.os }}-gradle- - name: Cache konan uses: actions/cache@v2 with: - path: | - ~/.konan/dependencies - ~/.konan/kotlin-native-prebuilt-mingw-* - key: ${{ runner.os }}-konan - restore-keys: ${{ runner.os }}-konan - - name: Build with Gradle - run: ./gradlew --build-cache build + path: ~/.konan + key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Build + run: ./gradlew build --no-daemon --stacktrace diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 000000000..83be65b50 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,43 @@ +name: deploy +on: workflow_dispatch + +jobs: + build: + strategy: + matrix: + os: [macOS-latest, windows-latest] + runs-on: ${{matrix.os}} + steps: + - name: Checkout the repo + uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Add msys to path + if: matrix.os == 'windows-latest' + run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" + - name: Cache gradle + uses: actions/cache@v2 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache konan + uses: actions/cache@v2 + with: + path: ~/.konan + key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Publish Mac Artifacts + if: matrix.os == 'macOS-latest' + run: ./gradlew publish --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} + env: + signingKey: ${{ secrets.SIGNING_KEY }} + - name: Publish Windows Artifacts + if: matrix.os == 'windows-latest' + run: ./gradlew publish --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} + env: + signingKey: ${{ secrets.SIGNING_KEY }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 743520885..000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,117 +0,0 @@ -name: Gradle release - -on: - release: - types: - - created - -jobs: - build-ubuntu: - runs-on: ubuntu-20.04 - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Install Chrome - run: | - sudo apt install -y libappindicator1 fonts-liberation - wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb - sudo dpkg -i google-chrome*.deb - - name: Cache gradle - uses: actions/cache@v2 - with: - path: | - .gradle - build - ~/.gradle - key: gradle - restore-keys: gradle - - - name: Cache konan - uses: actions/cache@v2 - with: - path: | - ~/.konan/dependencies - ~/.konan/kotlin-native-prebuilt-linux-* - key: ${{ runner.os }}-konan - restore-keys: ${{ runner.os }}-konan - - name: Build with Gradle - run: ./gradlew -Dorg.gradle.daemon=false --build-cache build - - name: Run release task - run: ./gradlew release -PbintrayUser=${{ secrets.BINTRAY_USER }} -PbintrayApiKey=${{ secrets.BINTRAY_KEY }} - - build-osx: - runs-on: macos-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Cache gradle - uses: actions/cache@v2 - with: - path: | - .gradle - build - ~/.gradle - key: gradle - restore-keys: gradle - - - name: Cache konan - uses: actions/cache@v2 - with: - path: | - ~/.konan/dependencies - ~/.konan/kotlin-native-prebuilt-macos-* - key: ${{ runner.os }}-konan - restore-keys: ${{ runner.os }}-konan - - name: Build with Gradle - run: sudo ./gradlew -Dorg.gradle.daemon=false --build-cache build - - name: Run release task - run: ./gradlew release -PbintrayUser=${{ secrets.BINTRAY_USER }} -PbintrayApiKey=${{ secrets.BINTRAY_KEY }} - - build-windows: - runs-on: windows-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Add msys to path - run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" - - name: Cache gradle - uses: actions/cache@v2 - with: - path: | - .gradle - build - ~/.gradle - key: ${{ runner.os }}-gradle - restore-keys: ${{ runner.os }}-gradle - - - name: Cache konan - uses: actions/cache@v2 - with: - path: | - ~/.konan/dependencies - ~/.konan/kotlin-native-prebuilt-mingw-* - key: ${{ runner.os }}-konan - restore-keys: ${{ runner.os }}-konan - - name: Build with Gradle - run: ./gradlew --build-cache build - - name: Run release task - run: ./gradlew release -PbintrayUser=${{ secrets.BINTRAY_USER }} -PbintrayApiKey=${{ secrets.BINTRAY_KEY }} - diff --git a/build.gradle.kts b/build.gradle.kts index 83123765d..9e2b42a3c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,5 @@ +import ru.mipt.npm.gradle.KSciencePublishingPlugin + plugins { id("ru.mipt.npm.gradle.project") } @@ -22,7 +24,14 @@ allprojects { } subprojects { - if (name.startsWith("kmath")) apply() + if (name.startsWith("kmath")) { + apply() + + val publishWindows by tasks.creating { + tasks.find { it.name == "publishMingwX64PublicationToSpaceRepository" }?.let { dependsOn(it) } + tasks.find { it.name == "publishMingwX64PublicationToSonatypeRepository" }?.let { dependsOn(it) } + } + } } readme { @@ -35,6 +44,6 @@ ksciencePublish { githubProject = "kmath" } -apiValidation{ +apiValidation { nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI") -} \ No newline at end of file +} diff --git a/gradle.properties b/gradle.properties index 88b90f27b..1a2a263ac 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,6 +3,7 @@ kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.mpp.stability.nowarn=true kotlin.native.enableDependencyPropagation=false kotlin.parallel.tasks.in.project=true +org.gradle.configureondemand=true org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m org.gradle.parallel=true systemProp.org.gradle.internal.publish.checksums.insecure=true From 13792b07b2eb9670654d52b44eefc739820bad90 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 28 Feb 2021 17:14:41 +0700 Subject: [PATCH 028/393] Add Touchlab notice --- .github/workflows/build.yml | 2 ++ .github/workflows/deploy.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 56f8721eb..3b9005997 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,3 +1,5 @@ +# Based on https://github.com/touchlab/Stately/blob/main/.github/workflows/build.yml + name: build on: [ push ] diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 83be65b50..40a703309 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,3 +1,5 @@ +# Based on https://github.com/touchlab/Stately/blob/main/.github/workflows/deploy.yml + name: deploy on: workflow_dispatch From a68b102e401ab7524de30130f11487ca931c3151 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 28 Feb 2021 20:23:02 +0700 Subject: [PATCH 029/393] Update deploy.yml --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 40a703309..9fcdec036 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -35,11 +35,11 @@ jobs: ${{ runner.os }}-gradle- - name: Publish Mac Artifacts if: matrix.os == 'macOS-latest' - run: ./gradlew publish --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} + run: ./gradlew publishAllPublicationsToSpaceRepository publishAllPublicationsToSonatypeRepository --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} env: signingKey: ${{ secrets.SIGNING_KEY }} - name: Publish Windows Artifacts if: matrix.os == 'windows-latest' - run: ./gradlew publish --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} + run: ./gradlew publishMingwX64PublicationToSpaceRepository publishMingwX64PublicationToSonatypeRepository --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} env: signingKey: ${{ secrets.SIGNING_KEY }} From 4ec33c6857f164ae58dc5408eb4180b7b26dbcd1 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 28 Feb 2021 20:23:16 +0700 Subject: [PATCH 030/393] Remove publishWindows task --- build.gradle.kts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9e2b42a3c..cb3cb1a3b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,14 +24,7 @@ allprojects { } subprojects { - if (name.startsWith("kmath")) { - apply() - - val publishWindows by tasks.creating { - tasks.find { it.name == "publishMingwX64PublicationToSpaceRepository" }?.let { dependsOn(it) } - tasks.find { it.name == "publishMingwX64PublicationToSonatypeRepository" }?.let { dependsOn(it) } - } - } + if (name.startsWith("kmath")) apply() } readme { From 30bd56d0f71261d20533d8720500be6faf96d265 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 28 Feb 2021 21:29:21 +0700 Subject: [PATCH 031/393] Support space credentials --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9fcdec036..997755816 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -35,11 +35,11 @@ jobs: ${{ runner.os }}-gradle- - name: Publish Mac Artifacts if: matrix.os == 'macOS-latest' - run: ./gradlew publishAllPublicationsToSpaceRepository publishAllPublicationsToSonatypeRepository --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} + run: ./gradlew publishAllPublicationsToSpaceRepository publishAllPublicationsToSonatypeRepository --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} -PspaceUser=${{ secrets.SPACE_USERNAME }} -PspacePassword=${{ secrets.SPACE_PASSWORD }} env: signingKey: ${{ secrets.SIGNING_KEY }} - name: Publish Windows Artifacts if: matrix.os == 'windows-latest' - run: ./gradlew publishMingwX64PublicationToSpaceRepository publishMingwX64PublicationToSonatypeRepository --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} + run: ./gradlew publishAllPublicationsToSpaceRepository publishAllPublicationsToSonatypeRepository --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} -PspaceUser=${{ secrets.SPACE_USERNAME }} -PspacePassword=${{ secrets.SPACE_PASSWORD }} env: signingKey: ${{ secrets.SIGNING_KEY }} From 4aa1df0628c5d531b518691eb8ab22b907946eb0 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 2 Mar 2021 09:32:36 +0000 Subject: [PATCH 032/393] Safe item method and view_as added --- .../space/kscience/kmath/tensors/RealTensorAlgebra.kt | 10 +++++++++- .../space/kscience/kmath/tensors/TensorAlgebra.kt | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 6023d2b72..24612a6aa 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -14,9 +14,13 @@ public class RealTensor( TensorStrides(shape), RealBuffer(buffer) ) { - override fun item(): Double = buffer[0] + override fun item(): Double { + check(buffer.size > 0) { "The tensor is empty" } + return buffer[0] + } } + public class RealTensorAlgebra : TensorPartialDivisionAlgebra { override fun Double.plus(other: RealTensor): RealTensor { @@ -116,6 +120,10 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra>{ //https://pytorch.org/docs/stable/tensor_view.html public fun TensorType.view(shape: IntArray): TensorType + public fun TensorType.view_as(other: TensorType): TensorType //https://pytorch.org/docs/stable/generated/torch.abs.html public fun TensorType.abs(): TensorType From ed007589cfc97d4b6c8d01a51719f2511d0ee3b3 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 2 Mar 2021 14:54:07 +0000 Subject: [PATCH 033/393] LU decomposition set up --- .../kscience/kmath/tensors/RealTensorAlgebra.kt | 13 +++++++++++++ .../space/kscience/kmath/tensors/TensorAlgebra.kt | 3 +++ 2 files changed, 16 insertions(+) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 24612a6aa..f234d7d6a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.linear.LupDecompositionFeature import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array @@ -164,7 +165,19 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { + /** + * Main first task for @AndreiKingsley + * Compare with the implementation of [LupDecomposition] + * and provide a common API + */ + TODO("Not yet implemented") + } + override fun RealTensor.svd(): Triple { + /** + * Main first task for @AlyaNovikova + */ TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index cddda7670..03f6f05c2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -66,6 +66,9 @@ public interface TensorPartialDivisionAlgebra public fun TensorType.log(): TensorType public fun TensorType.logAssign(): Unit + //https://pytorch.org/docs/stable/generated/torch.lu.html + public fun TensorType.lu(): Pair + //https://pytorch.org/docs/stable/generated/torch.svd.html public fun TensorType.svd(): Triple From 90f4ff06fd76fb60f4966d8d60fa31c6b4ebf96f Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 4 Mar 2021 13:22:28 +0000 Subject: [PATCH 034/393] Basic tasks for Alya and Andrei --- .../kmath/tensors/RealTensorAlgebra.kt | 58 +++++++++++-------- .../kscience/kmath/tensors/TensorAlgebra.kt | 7 ++- .../kscience/kmath/tensors/TensorStructure.kt | 4 ++ 3 files changed, 44 insertions(+), 25 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index f234d7d6a..cad01c4d0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,6 +1,5 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.linear.LupDecompositionFeature import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array @@ -15,6 +14,9 @@ public class RealTensor( TensorStrides(shape), RealBuffer(buffer) ) { + /* + * TODO: Andrei remove item() + */ override fun item(): Double { check(buffer.size > 0) { "The tensor is empty" } return buffer[0] @@ -24,6 +26,10 @@ public class RealTensor( public class RealTensorAlgebra : TensorPartialDivisionAlgebra { + override fun RealTensor.value(): Double { + TODO("Andrei") + } + override fun Double.plus(other: RealTensor): RealTensor { val n = other.buffer.size val arr = other.buffer.array @@ -34,95 +40,95 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { + TODO("Not yet implemented") + } + override fun RealTensor.svd(): Triple { /** * Main first task for @AlyaNovikova diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 03f6f05c2..b2586e1e9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -1,7 +1,9 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Algebra_over_Ring -public interface TensorAlgebra>{ +public interface TensorAlgebra> { + + public fun TensorType.value(): T public operator fun T.plus(other: TensorType): TensorType public operator fun TensorType.plus(value: T): TensorType @@ -69,6 +71,9 @@ public interface TensorPartialDivisionAlgebra //https://pytorch.org/docs/stable/generated/torch.lu.html public fun TensorType.lu(): Pair + //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html + public fun lu_unpack(A_LU: TensorType, pivots: TensorType): Triple + //https://pytorch.org/docs/stable/generated/torch.svd.html public fun TensorType.svd(): Triple diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt index 6d2d855b6..3775ea2e5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt @@ -3,6 +3,10 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDStructure public interface TensorStructure : MutableNDStructure { + + /* + * TODO: Andrei remove item() and value() + */ public fun item(): T // A tensor can have empty shape, in which case it represents just a value From 8ae8ebe871c8ece0964f98b7062fbe1b10278d1f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 8 Mar 2021 21:03:48 +0300 Subject: [PATCH 035/393] Fully refactor algebra split ScaleOperations from Space. --- .github/workflows/build.yml | 3 +- .github/workflows/{deploy.yml => publish.yml} | 38 +- CHANGELOG.md | 5 + build.gradle.kts | 7 +- .../space/kscience/kmath/ast/expressions.kt | 4 +- .../kmath/structures/ParallelRealNDField.kt | 38 +- gradle.properties | 7 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../space/kscience/kmath/ast/MstAlgebra.kt | 58 ++- .../TestESTreeConsistencyWithInterpreter.kt | 24 +- .../asm/TestAsmConsistencyWithInterpreter.kt | 24 +- .../DerivativeStructureExpression.kt | 13 +- .../kscience/kmath/commons/linear/CMMatrix.kt | 4 +- .../space/kscience/kmath/complex/Complex.kt | 28 +- .../kscience/kmath/complex/ComplexNDField.kt | 35 +- .../kscience/kmath/complex/Quaternion.kt | 20 +- .../complex/ExpressionFieldForComplexTest.kt | 6 +- kmath-core/README.md | 55 -- kmath-core/api/kmath-core.api | 480 +++++------------- .../kmath/domains/HyperSquareDomain.kt | 19 +- .../kscience/kmath/domains/RealDomain.kt | 30 +- .../kmath/domains/UnconstrainedDomain.kt | 12 +- .../kmath/domains/UnivariateDomain.kt | 31 +- .../FunctionalExpressionAlgebra.kt | 35 +- .../kmath/expressions/SimpleAutoDiff.kt | 127 ++--- .../kscience/kmath/linear/BufferMatrix.kt | 12 +- .../kscience/kmath/linear/MatrixContext.kt | 11 +- .../kmath/linear/RealMatrixContext.kt | 18 +- .../kscience/kmath/linear/VectorSpace.kt | 35 +- .../kscience/kmath/nd/BufferNDAlgebra.kt | 27 +- .../space/kscience/kmath/nd/NDAlgebra.kt | 32 +- .../space/kscience/kmath/nd/RealNDField.kt | 8 +- .../space/kscience/kmath/nd/ShortNDRing.kt | 4 +- .../kscience/kmath/operations/Algebra.kt | 57 +-- .../kmath/operations/AlgebraElements.kt | 51 +- .../space/kscience/kmath/operations/BigInt.kt | 17 +- .../kmath/operations/NumericAlgebra.kt | 45 +- .../kmath/operations/OptionalOperations.kt | 202 ++++---- .../kmath/operations/algebraExtensions.kt | 12 +- .../kscience/kmath/operations/numbers.kt | 65 +-- .../kmath/structures/RealBufferField.kt | 45 +- .../kmath/expressions/ExpressionFieldTest.kt | 4 +- .../kscience/kmath/testutils/FieldVerifier.kt | 5 +- .../kscience/kmath/testutils/RingVerifier.kt | 6 +- .../kscience/kmath/testutils/SpaceVerifier.kt | 10 +- .../kscience/kmath/operations/BigNumbers.kt | 17 +- .../space/kscience/kmath/chains/flowExtra.kt | 4 +- .../kscience/kmath/ejml/EjmlMatrixContext.kt | 10 +- .../kscience/kmath/functions/Polynomial.kt | 15 +- .../kmath/interpolation/SplineInterpolator.kt | 6 +- .../kmath/geometry/Euclidean2DSpace.kt | 9 +- .../kmath/geometry/Euclidean3DSpace.kt | 10 +- .../kmath/histogram/IndexedHistogramSpace.kt | 14 +- .../kmath/histogram/RealHistogramSpace.kt | 4 + .../kmath/histogram/TreeHistogramSpace.kt | 11 +- .../kmath/histogram/UnivariateHistogram.kt | 2 + .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 27 +- .../kscience/kmath/stat/SamplerAlgebra.kt | 15 +- .../space/kscience/kmath/stat/Statistic.kt | 20 +- kmath-viktor/api/kmath-viktor.api | 11 +- .../kmath/viktor/ViktorNDStructure.kt | 12 +- settings.gradle.kts | 7 +- 62 files changed, 869 insertions(+), 1096 deletions(-) rename .github/workflows/{deploy.yml => publish.yml} (52%) delete mode 100644 kmath-core/README.md diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3b9005997..25f2cfd0d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,5 @@ -# Based on https://github.com/touchlab/Stately/blob/main/.github/workflows/build.yml +name: Gradle build -name: build on: [ push ] jobs: diff --git a/.github/workflows/deploy.yml b/.github/workflows/publish.yml similarity index 52% rename from .github/workflows/deploy.yml rename to .github/workflows/publish.yml index 997755816..42fa6d3b6 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/publish.yml @@ -1,10 +1,15 @@ -# Based on https://github.com/touchlab/Stately/blob/main/.github/workflows/deploy.yml +name: Gradle publish -name: deploy -on: workflow_dispatch +on: + workflow_dispatch: + release: + types: + - created jobs: - build: + publish: + environment: + name: publish strategy: matrix: os: [macOS-latest, windows-latest] @@ -33,13 +38,22 @@ jobs: key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} restore-keys: | ${{ runner.os }}-gradle- - - name: Publish Mac Artifacts - if: matrix.os == 'macOS-latest' - run: ./gradlew publishAllPublicationsToSpaceRepository publishAllPublicationsToSonatypeRepository --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} -PspaceUser=${{ secrets.SPACE_USERNAME }} -PspacePassword=${{ secrets.SPACE_PASSWORD }} - env: - signingKey: ${{ secrets.SIGNING_KEY }} - name: Publish Windows Artifacts if: matrix.os == 'windows-latest' - run: ./gradlew publishAllPublicationsToSpaceRepository publishAllPublicationsToSonatypeRepository --no-daemon --stacktrace -PsonatypePublish=true -PsonatypeUser=${{ secrets.SONATYPE_USERNAME }} -PsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} -PspaceUser=${{ secrets.SPACE_USERNAME }} -PspacePassword=${{ secrets.SPACE_PASSWORD }} - env: - signingKey: ${{ secrets.SIGNING_KEY }} + run: > + ./gradlew release --no-daemon + -Ppublishing.enabled=true + -Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }} + -Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }} + -Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }} + -Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }} + - name: Publish Mac Artifacts + if: matrix.os == 'macOS-latest' + run: > + ./gradlew release --no-daemon + -Ppublishing.enabled=true + -Ppublishing.platform=macosX64 + -Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }} + -Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }} + -Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }} + -Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index c7033df7f..db3b65024 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,17 @@ ## [Unreleased] ### Added +- Intrinsic value `two` for ExtendedField to work with hyperbolic functions +- ScaleOperations interface ### Changed +- Exponential operations merged with hyperbolic functions ### Deprecated ### Removed +- Nearest in Domain. To be implemented in geometry package. +- Number multiplication and division in main Algebra chain ### Fixed diff --git a/build.gradle.kts b/build.gradle.kts index cb3cb1a3b..41e8a3468 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,7 +20,7 @@ allprojects { } group = "space.kscience" - version = "0.2.0" + version = "0.3.0" } subprojects { @@ -32,9 +32,8 @@ readme { } ksciencePublish { - spaceRepo = "https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven" - bintrayRepo = "kscience" - githubProject = "kmath" + github("kmath") + space() } apiValidation { diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt index ee0f4a492..8d6851ef8 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt @@ -6,10 +6,10 @@ import space.kscience.kmath.operations.RealField fun main() { val expr = RealField.mstInField { val x = bindSymbol("x") - x * 2.0 + 2.0 / x - 16.0 + x * 2.0 + 2.0 * one / x - 16.0 } - repeat(10000000){ + repeat(10000000) { expr.invoke("x" to 1.0) } } \ No newline at end of file diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt index 111cfec80..0c914468d 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt @@ -3,8 +3,8 @@ package space.kscience.kmath.structures import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.operations.NumbersAddOperations import space.kscience.kmath.operations.RealField -import space.kscience.kmath.operations.RingWithNumbers import java.util.* import java.util.stream.IntStream @@ -15,7 +15,7 @@ import java.util.stream.IntStream class StreamRealNDField( override val shape: IntArray, ) : NDField, - RingWithNumbers>, + NumbersAddOperations>, ExtendedField> { private val strides = DefaultStrides(shape) @@ -79,25 +79,29 @@ class StreamRealNDField( return NDBuffer(strides, array.asBuffer()) } - override fun power(arg: NDStructure, pow: Number): NDBuffer = arg.map() { power(it, pow) } + override fun NDStructure.unaryMinus(): NDStructure = map { -it } - override fun exp(arg: NDStructure): NDBuffer = arg.map() { exp(it) } + override fun scale(a: NDStructure, value: Double): NDStructure = a.map { it * value } - override fun ln(arg: NDStructure): NDBuffer = arg.map() { ln(it) } + override fun power(arg: NDStructure, pow: Number): NDBuffer = arg.map { power(it, pow) } - override fun sin(arg: NDStructure): NDBuffer = arg.map() { sin(it) } - override fun cos(arg: NDStructure): NDBuffer = arg.map() { cos(it) } - override fun tan(arg: NDStructure): NDBuffer = arg.map() { tan(it) } - override fun asin(arg: NDStructure): NDBuffer = arg.map() { asin(it) } - override fun acos(arg: NDStructure): NDBuffer = arg.map() { acos(it) } - override fun atan(arg: NDStructure): NDBuffer = arg.map() { atan(it) } + override fun exp(arg: NDStructure): NDBuffer = arg.map { exp(it) } - override fun sinh(arg: NDStructure): NDBuffer = arg.map() { sinh(it) } - override fun cosh(arg: NDStructure): NDBuffer = arg.map() { cosh(it) } - override fun tanh(arg: NDStructure): NDBuffer = arg.map() { tanh(it) } - override fun asinh(arg: NDStructure): NDBuffer = arg.map() { asinh(it) } - override fun acosh(arg: NDStructure): NDBuffer = arg.map() { acosh(it) } - override fun atanh(arg: NDStructure): NDBuffer = arg.map() { atanh(it) } + override fun ln(arg: NDStructure): NDBuffer = arg.map { ln(it) } + + override fun sin(arg: NDStructure): NDBuffer = arg.map { sin(it) } + override fun cos(arg: NDStructure): NDBuffer = arg.map { cos(it) } + override fun tan(arg: NDStructure): NDBuffer = arg.map { tan(it) } + override fun asin(arg: NDStructure): NDBuffer = arg.map { asin(it) } + override fun acos(arg: NDStructure): NDBuffer = arg.map { acos(it) } + override fun atan(arg: NDStructure): NDBuffer = arg.map { atan(it) } + + override fun sinh(arg: NDStructure): NDBuffer = arg.map { sinh(it) } + override fun cosh(arg: NDStructure): NDBuffer = arg.map { cosh(it) } + override fun tanh(arg: NDStructure): NDBuffer = arg.map { tanh(it) } + override fun asinh(arg: NDStructure): NDBuffer = arg.map { asinh(it) } + override fun acosh(arg: NDStructure): NDBuffer = arg.map { acosh(it) } + override fun atanh(arg: NDStructure): NDBuffer = arg.map { atanh(it) } } fun NDAlgebra.Companion.realWithStream(vararg shape: Int): StreamRealNDField = StreamRealNDField(shape) \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 1a2a263ac..aadc76c52 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,9 +1,10 @@ kotlin.code.style=official -kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.mpp.stability.nowarn=true -kotlin.native.enableDependencyPropagation=false kotlin.parallel.tasks.in.project=true org.gradle.configureondemand=true org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m org.gradle.parallel=true -systemProp.org.gradle.internal.publish.checksums.insecure=true + +kotlin.mpp.enableGranularSourceSetsMetadata=true +kotlin.native.enableDependencyPropagation=false + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2a563242c..442d9132e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt index 7bea65684..047ee187d 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt @@ -20,8 +20,8 @@ public object MstAlgebra : NumericAlgebra { /** * [Space] over [MST] nodes. */ -public object MstSpace : Space, NumericAlgebra { - public override val zero: MST.Numeric by lazy { number(0.0) } +public object MstSpace : Space, NumericAlgebra, ScaleOperations { + public override val zero: MST.Numeric = number(0.0) public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value) @@ -35,8 +35,8 @@ public object MstSpace : Space, NumericAlgebra { public override operator fun MST.minus(b: MST): MST.Binary = binaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this, b) - public override fun multiply(a: MST, k: Number): MST.Binary = - binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(k)) + public override fun scale(a: MST, value: Double): MST.Binary = + binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(value)) public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = MstAlgebra.binaryOperationFunction(operation) @@ -49,16 +49,17 @@ public object MstSpace : Space, NumericAlgebra { * [Ring] over [MST] nodes. */ @OptIn(UnstableKMathAPI::class) -public object MstRing : Ring, RingWithNumbers { - public override val zero: MST.Numeric - get() = MstSpace.zero - - public override val one: MST.Numeric by lazy { number(1.0) } +public object MstRing : Ring, NumbersAddOperations, ScaleOperations { + public override val zero: MST.Numeric = MstSpace.zero + public override val one: MST.Numeric = number(1.0) public override fun number(value: Number): MST.Numeric = MstSpace.number(value) public override fun bindSymbol(value: String): MST.Symbolic = MstSpace.bindSymbol(value) public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b) - public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k) + + public override fun scale(a: MST, value: Double): MST.Binary = + MstSpace.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstSpace.number(value)) + public override fun multiply(a: MST, b: MST): MST.Binary = binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b) @@ -77,17 +78,18 @@ public object MstRing : Ring, RingWithNumbers { * [Field] over [MST] nodes. */ @OptIn(UnstableKMathAPI::class) -public object MstField : Field, RingWithNumbers { - public override val zero: MST.Numeric - get() = MstRing.zero +public object MstField : Field, NumbersAddOperations, ScaleOperations { + public override val zero: MST.Numeric get() = MstRing.zero - public override val one: MST.Numeric - get() = MstRing.one + public override val one: MST.Numeric get() = MstRing.one public override fun bindSymbol(value: String): MST.Symbolic = MstRing.bindSymbol(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value) public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b) - public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k) + + public override fun scale(a: MST, value: Double): MST.Binary = + MstSpace.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstSpace.number(value)) + public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b) public override fun divide(a: MST, b: MST): MST.Binary = binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b) @@ -107,11 +109,8 @@ public object MstField : Field, RingWithNumbers { * [ExtendedField] over [MST] nodes. */ public object MstExtendedField : ExtendedField, NumericAlgebra { - public override val zero: MST.Numeric - get() = MstField.zero - - public override val one: MST.Numeric - get() = MstField.one + public override val zero: MST.Numeric = MstField.zero + public override val one: MST.Numeric = MstField.one public override fun bindSymbol(value: String): MST.Symbolic = MstField.bindSymbol(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value) @@ -121,14 +120,17 @@ public object MstExtendedField : ExtendedField, NumericAlgebra { public override fun asin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ASIN_OPERATION)(arg) public override fun acos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ACOS_OPERATION)(arg) public override fun atan(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ATAN_OPERATION)(arg) - public override fun sinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.SINH_OPERATION)(arg) - public override fun cosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.COSH_OPERATION)(arg) - public override fun tanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.TANH_OPERATION)(arg) - public override fun asinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ASINH_OPERATION)(arg) - public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ACOSH_OPERATION)(arg) - public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ATANH_OPERATION)(arg) + public override fun sinh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.SINH_OPERATION)(arg) + public override fun cosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.COSH_OPERATION)(arg) + public override fun tanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.TANH_OPERATION)(arg) + public override fun asinh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ASINH_OPERATION)(arg) + public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ACOSH_OPERATION)(arg) + public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ATANH_OPERATION)(arg) public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b) - public override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k) + + public override fun scale(a: MST, value: Double): MST = + binaryOperation(SpaceOperations.PLUS_OPERATION, a, number(value)) + public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b) public override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b) public override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt index 492a5d11f..c91cc4daf 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt @@ -15,9 +15,9 @@ internal class TestESTreeConsistencyWithInterpreter { val res1 = MstSpace.mstInSpace { binaryOperationFunction("+")( unaryOperationFunction("+")( - number(3.toByte()) - (number(2.toByte()) + (multiply( + number(3.toByte()) - (number(2.toByte()) + (scale( add(number(1), number(1)), - 2 + 2.0 ) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) ), @@ -28,9 +28,9 @@ internal class TestESTreeConsistencyWithInterpreter { val res2 = MstSpace.mstInSpace { binaryOperationFunction("+")( unaryOperationFunction("+")( - number(3.toByte()) - (number(2.toByte()) + (multiply( + number(3.toByte()) - (number(2.toByte()) + (scale( add(number(1), number(1)), - 2 + 2.0 ) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) ), @@ -46,9 +46,9 @@ internal class TestESTreeConsistencyWithInterpreter { val res1 = ByteRing.mstInRing { binaryOperationFunction("+")( unaryOperationFunction("+")( - (bindSymbol("x") - (2.toByte() + (multiply( + (bindSymbol("x") - (2.toByte() + (scale( add(number(1), number(1)), - 2 + 2.0 ) + 1.toByte()))) * 3.0 - 1.toByte() ), @@ -59,9 +59,9 @@ internal class TestESTreeConsistencyWithInterpreter { val res2 = ByteRing.mstInRing { binaryOperationFunction("+")( unaryOperationFunction("+")( - (bindSymbol("x") - (2.toByte() + (multiply( + (bindSymbol("x") - (2.toByte() + (scale( add(number(1), number(1)), - 2 + 2.0 ) + 1.toByte()))) * 3.0 - 1.toByte() ), number(1) @@ -75,7 +75,7 @@ internal class TestESTreeConsistencyWithInterpreter { fun realField() { val res1 = RealField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero @@ -83,7 +83,7 @@ internal class TestESTreeConsistencyWithInterpreter { val res2 = RealField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero @@ -96,7 +96,7 @@ internal class TestESTreeConsistencyWithInterpreter { fun complexField() { val res1 = ComplexField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero @@ -104,7 +104,7 @@ internal class TestESTreeConsistencyWithInterpreter { val res2 = ComplexField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt index 0f2328db6..5c6297f3f 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt @@ -15,9 +15,9 @@ internal class TestAsmConsistencyWithInterpreter { val res1 = MstSpace.mstInSpace { binaryOperationFunction("+")( unaryOperationFunction("+")( - number(3.toByte()) - (number(2.toByte()) + (multiply( + number(3.toByte()) - (number(2.toByte()) + (scale( add(number(1), number(1)), - 2 + 2.0 ) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) ), @@ -28,9 +28,9 @@ internal class TestAsmConsistencyWithInterpreter { val res2 = MstSpace.mstInSpace { binaryOperationFunction("+")( unaryOperationFunction("+")( - number(3.toByte()) - (number(2.toByte()) + (multiply( + number(3.toByte()) - (number(2.toByte()) + (scale( add(number(1), number(1)), - 2 + 2.0 ) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) ), @@ -46,9 +46,9 @@ internal class TestAsmConsistencyWithInterpreter { val res1 = ByteRing.mstInRing { binaryOperationFunction("+")( unaryOperationFunction("+")( - (bindSymbol("x") - (2.toByte() + (multiply( + (bindSymbol("x") - (2.toByte() + (scale( add(number(1), number(1)), - 2 + 2.0 ) + 1.toByte()))) * 3.0 - 1.toByte() ), @@ -59,9 +59,9 @@ internal class TestAsmConsistencyWithInterpreter { val res2 = ByteRing.mstInRing { binaryOperationFunction("+")( unaryOperationFunction("+")( - (bindSymbol("x") - (2.toByte() + (multiply( + (bindSymbol("x") - (2.toByte() + (scale( add(number(1), number(1)), - 2 + 2.0 ) + 1.toByte()))) * 3.0 - 1.toByte() ), number(1) @@ -75,7 +75,7 @@ internal class TestAsmConsistencyWithInterpreter { fun realField() { val res1 = RealField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero @@ -83,7 +83,7 @@ internal class TestAsmConsistencyWithInterpreter { val res2 = RealField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero @@ -96,7 +96,7 @@ internal class TestAsmConsistencyWithInterpreter { fun complexField() { val res1 = ComplexField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero @@ -104,7 +104,7 @@ internal class TestAsmConsistencyWithInterpreter { val res2 = ComplexField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 8342a8071..b74167c3f 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -4,7 +4,7 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure import space.kscience.kmath.expressions.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.ExtendedField -import space.kscience.kmath.operations.RingWithNumbers +import space.kscience.kmath.operations.NumbersAddOperations /** * A field over commons-math [DerivativeStructure]. @@ -16,7 +16,8 @@ import space.kscience.kmath.operations.RingWithNumbers public class DerivativeStructureField( public val order: Int, bindings: Map, -) : ExtendedField, ExpressionAlgebra, RingWithNumbers { +) : ExtendedField, ExpressionAlgebra, + NumbersAddOperations { public val numberOfVariables: Int = bindings.size public override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) } @@ -62,13 +63,11 @@ public class DerivativeStructureField( public fun DerivativeStructure.derivative(vararg symbols: Symbol): Double = derivative(symbols.toList()) + override fun DerivativeStructure.unaryMinus(): DerivativeStructure = negate() + public override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b) - public override fun multiply(a: DerivativeStructure, k: Number): DerivativeStructure = when (k) { - is Double -> a.multiply(k) - is Int -> a.multiply(k) - else -> a.multiply(k.toDouble()) - } + public override fun scale(a: DerivativeStructure, value: Double): DerivativeStructure = a.multiply(value) public override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b) public override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index 3638b9808..537da5947 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -101,8 +101,8 @@ public object CMMatrixContext : MatrixContext { public override operator fun Matrix.minus(b: Matrix): CMMatrix = CMMatrix(toCM().origin.subtract(b.toCM().origin)) - public override fun multiply(a: Matrix, k: Number): CMMatrix = - CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble())) +// public override fun multiply(a: Matrix, k: Number): CMMatrix = +// CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble())) public override operator fun Matrix.times(value: Double): CMMatrix = produce(rowNum, colNum) { i, j -> get(i, j) * value } diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt index deadfda5b..a73fb0201 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt @@ -4,10 +4,7 @@ import space.kscience.kmath.memory.MemoryReader import space.kscience.kmath.memory.MemorySpec import space.kscience.kmath.memory.MemoryWriter import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.ExtendedField -import space.kscience.kmath.operations.FieldElement -import space.kscience.kmath.operations.Norm -import space.kscience.kmath.operations.RingWithNumbers +import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MemoryBuffer import space.kscience.kmath.structures.MutableBuffer @@ -47,7 +44,8 @@ private val PI_DIV_2 = Complex(PI / 2, 0) * A field of [Complex]. */ @OptIn(UnstableKMathAPI::class) -public object ComplexField : ExtendedField, Norm, RingWithNumbers { +public object ComplexField : ExtendedField, Norm, NumbersAddOperations, + ScaleOperations { public override val zero: Complex = 0.0.toComplex() public override val one: Complex = 1.0.toComplex() @@ -56,8 +54,14 @@ public object ComplexField : ExtendedField, Norm, Rin */ public val i: Complex by lazy { Complex(0.0, 1.0) } + override fun Complex.unaryMinus(): Complex = Complex(-re, -im) + + override fun number(value: Number): Complex = Complex(value.toDouble(), 0.0) + + override fun scale(a: Complex, value: Double): Complex = Complex(a.re * value, a.im * value) + public override fun add(a: Complex, b: Complex): Complex = Complex(a.re + b.re, a.im + b.im) - public override fun multiply(a: Complex, k: Number): Complex = Complex(a.re * k.toDouble(), a.im * k.toDouble()) +// public override fun multiply(a: Complex, k: Number): Complex = Complex(a.re * k.toDouble(), a.im * k.toDouble()) public override fun multiply(a: Complex, b: Complex): Complex = Complex(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re) @@ -86,8 +90,10 @@ public object ComplexField : ExtendedField, Norm, Rin } } - public override fun sin(arg: Complex): Complex = i * (exp(-i * arg) - exp(i * arg)) / 2 - public override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2 + override operator fun Complex.div(k: Number): Complex = Complex(re / k.toDouble(), im / k.toDouble()) + + public override fun sin(arg: Complex): Complex = i * (exp(-i * arg) - exp(i * arg)) / 2.0 + public override fun cos(arg: Complex): Complex = (exp(-i * arg) + exp(i * arg)) / 2.0 public override fun tan(arg: Complex): Complex { val e1 = exp(-i * arg) @@ -159,7 +165,8 @@ public object ComplexField : ExtendedField, Norm, Rin public override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg) - public override fun bindSymbol(value: String): Complex = if (value == "i") i else super.bindSymbol(value) + public override fun bindSymbol(value: String): Complex = + if (value == "i") i else super.bindSymbol(value) } /** @@ -181,7 +188,8 @@ public data class Complex(val re: Double, val im: Double) : FieldElement(shape, ComplexField, Buffer.Companion::complex), - RingWithNumbers>, + NumbersAddOperations>, ExtendedField> { override val zero: NDBuffer by lazy { produce { zero } } @@ -29,6 +29,7 @@ public class ComplexNDField( val d = value.toComplex() // minimize conversions return produce { d } } + // // @Suppress("OVERRIDE_BY_INLINE") // override inline fun map( @@ -75,25 +76,25 @@ public class ComplexNDField( // return BufferedNDFieldElement(this, buffer) // } - override fun power(arg: NDStructure, pow: Number): NDBuffer = arg.map() { power(it, pow) } + override fun power(arg: NDStructure, pow: Number): NDBuffer = arg.map { power(it, pow) } - override fun exp(arg: NDStructure): NDBuffer = arg.map() { exp(it) } + override fun exp(arg: NDStructure): NDBuffer = arg.map { exp(it) } - override fun ln(arg: NDStructure): NDBuffer = arg.map() { ln(it) } + override fun ln(arg: NDStructure): NDBuffer = arg.map { ln(it) } - override fun sin(arg: NDStructure): NDBuffer = arg.map() { sin(it) } - override fun cos(arg: NDStructure): NDBuffer = arg.map() { cos(it) } - override fun tan(arg: NDStructure): NDBuffer = arg.map() { tan(it) } - override fun asin(arg: NDStructure): NDBuffer = arg.map() { asin(it) } - override fun acos(arg: NDStructure): NDBuffer = arg.map() { acos(it) } - override fun atan(arg: NDStructure): NDBuffer = arg.map() { atan(it) } + override fun sin(arg: NDStructure): NDBuffer = arg.map { sin(it) } + override fun cos(arg: NDStructure): NDBuffer = arg.map { cos(it) } + override fun tan(arg: NDStructure): NDBuffer = arg.map { tan(it) } + override fun asin(arg: NDStructure): NDBuffer = arg.map { asin(it) } + override fun acos(arg: NDStructure): NDBuffer = arg.map { acos(it) } + override fun atan(arg: NDStructure): NDBuffer = arg.map { atan(it) } - override fun sinh(arg: NDStructure): NDBuffer = arg.map() { sinh(it) } - override fun cosh(arg: NDStructure): NDBuffer = arg.map() { cosh(it) } - override fun tanh(arg: NDStructure): NDBuffer = arg.map() { tanh(it) } - override fun asinh(arg: NDStructure): NDBuffer = arg.map() { asinh(it) } - override fun acosh(arg: NDStructure): NDBuffer = arg.map() { acosh(it) } - override fun atanh(arg: NDStructure): NDBuffer = arg.map() { atanh(it) } + override fun sinh(arg: NDStructure): NDBuffer = arg.map { sinh(it) } + override fun cosh(arg: NDStructure): NDBuffer = arg.map { cosh(it) } + override fun tanh(arg: NDStructure): NDBuffer = arg.map { tanh(it) } + override fun asinh(arg: NDStructure): NDBuffer = arg.map { asinh(it) } + override fun acosh(arg: NDStructure): NDBuffer = arg.map { acosh(it) } + override fun atanh(arg: NDStructure): NDBuffer = arg.map { atanh(it) } } diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index 4a15e7423..d391aff18 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -37,7 +37,7 @@ public val Quaternion.r: Double */ @OptIn(UnstableKMathAPI::class) public object QuaternionField : Field, Norm, PowerOperations, - ExponentialOperations, RingWithNumbers { + ExponentialOperations, NumbersAddOperations, ScaleOperations { override val zero: Quaternion = 0.toQuaternion() override val one: Quaternion = 1.toQuaternion() @@ -59,10 +59,8 @@ public object QuaternionField : Field, Norm, public override fun add(a: Quaternion, b: Quaternion): Quaternion = Quaternion(a.w + b.w, a.x + b.x, a.y + b.y, a.z + b.z) - public override fun multiply(a: Quaternion, k: Number): Quaternion { - val d = k.toDouble() - return Quaternion(a.w * d, a.x * d, a.y * d, a.z * d) - } + public override fun scale(a: Quaternion, value: Double): Quaternion = + Quaternion(a.w * value, a.x * value, a.y * value, a.z * value) public override fun multiply(a: Quaternion, b: Quaternion): Quaternion = Quaternion( a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z, @@ -173,6 +171,15 @@ public object QuaternionField : Field, Norm, "k" -> k else -> super.bindSymbol(value) } + + override fun number(value: Number): Quaternion =value.toQuaternion() + + public override fun sinh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / 2.0 + public override fun cosh(arg: Quaternion): Quaternion = (exp(arg) + exp(-arg)) / 2.0 + public override fun tanh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg)) + public override fun asinh(arg: Quaternion): Quaternion = ln(sqrt(arg * arg + one) + arg) + public override fun acosh(arg: Quaternion): Quaternion = ln(arg + sqrt((arg - one) * (arg + one))) + public override fun atanh(arg: Quaternion): Quaternion = (ln(arg + one) - ln(one - arg)) / 2.0 } /** @@ -207,8 +214,7 @@ public data class Quaternion( require(!z.isNaN()) { "x-component of quaternion is not-a-number" } } - public override val context: QuaternionField - get() = QuaternionField + public override val context: QuaternionField get() = QuaternionField /** * Returns a string representation of this quaternion. diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt index 43560b35a..81a131318 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt @@ -4,7 +4,6 @@ import space.kscience.kmath.expressions.FunctionalExpressionField import space.kscience.kmath.expressions.bindSymbol import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.symbol -import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals @@ -13,14 +12,11 @@ internal class ExpressionFieldForComplexTest { @Test fun testComplex() { - val context = FunctionalExpressionField(ComplexField) - - val expression = context { + val expression = FunctionalExpressionField(ComplexField).run { val x = bindSymbol(x) x * x + 2 * x + one } assertEquals(expression(x to Complex(1.0, 0.0)), Complex(4.0, 0.0)) - //assertEquals(expression(), Complex(9.0, 0.0)) } } diff --git a/kmath-core/README.md b/kmath-core/README.md deleted file mode 100644 index 54380670d..000000000 --- a/kmath-core/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# The Core Module (`kmath-core`) - -The core features of KMath: - - - [algebras](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields. - - [nd](src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures and operations on them. - - [linear](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition. - - [buffers](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure - - [expressions](src/commonMain/kotlin/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of -objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high -performance calculations to code generation. - - [domains](src/commonMain/kotlin/kscience/kmath/domains) : Domains - - [autodif](src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation - - -> #### Artifact: -> -> This module artifact: `space.kscience:kmath-core:0.2.0`. -> -> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) -> -> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion) -> -> **Gradle:** -> -> ```gradle -> repositories { -> maven { url 'https://repo.kotlin.link' } -> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } -> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } -> } -> -> dependencies { -> implementation 'space.kscience:kmath-core:0.2.0' -> } -> ``` -> **Gradle Kotlin DSL:** -> -> ```kotlin -> repositories { -> maven("https://repo.kotlin.link") -> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap -> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") -> } -> -> dependencies { -> implementation("space.kscience:kmath-core:0.2.0") -> } -> ``` diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 4a21a3d7e..0efe430ad 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -3,70 +3,6 @@ public abstract interface class space/kscience/kmath/domains/Domain { public abstract fun getDimension ()I } -public final class space/kscience/kmath/domains/HyperSquareDomain : space/kscience/kmath/domains/RealDomain { - public fun (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)V - public fun contains (Lspace/kscience/kmath/structures/Buffer;)Z - public fun getDimension ()I - public fun getLowerBound (I)Ljava/lang/Double; - public fun getLowerBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double; - public fun getUpperBound (I)Ljava/lang/Double; - public fun getUpperBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double; - public fun nearestInDomain (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun volume ()D -} - -public abstract interface class space/kscience/kmath/domains/RealDomain : space/kscience/kmath/domains/Domain { - public abstract fun getLowerBound (I)Ljava/lang/Double; - public abstract fun getLowerBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double; - public abstract fun getUpperBound (I)Ljava/lang/Double; - public abstract fun getUpperBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double; - public abstract fun nearestInDomain (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun volume ()D -} - -public final class space/kscience/kmath/domains/UnconstrainedDomain : space/kscience/kmath/domains/RealDomain { - public fun (I)V - public fun contains (Lspace/kscience/kmath/structures/Buffer;)Z - public fun getDimension ()I - public fun getLowerBound (I)Ljava/lang/Double; - public fun getLowerBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double; - public fun getUpperBound (I)Ljava/lang/Double; - public fun getUpperBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double; - public fun nearestInDomain (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun volume ()D -} - -public final class space/kscience/kmath/domains/UnivariateDomain : space/kscience/kmath/domains/RealDomain { - public static final synthetic fun box-impl (Lkotlin/ranges/ClosedFloatingPointRange;)Lspace/kscience/kmath/domains/UnivariateDomain; - public static fun constructor-impl (Lkotlin/ranges/ClosedFloatingPointRange;)Lkotlin/ranges/ClosedFloatingPointRange; - public fun contains (Lspace/kscience/kmath/structures/Buffer;)Z - public static final fun contains-impl (Lkotlin/ranges/ClosedFloatingPointRange;D)Z - public static fun contains-impl (Lkotlin/ranges/ClosedFloatingPointRange;Lspace/kscience/kmath/structures/Buffer;)Z - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Lkotlin/ranges/ClosedFloatingPointRange;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Lkotlin/ranges/ClosedFloatingPointRange;Lkotlin/ranges/ClosedFloatingPointRange;)Z - public fun getDimension ()I - public static fun getDimension-impl (Lkotlin/ranges/ClosedFloatingPointRange;)I - public fun getLowerBound (I)Ljava/lang/Double; - public fun getLowerBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double; - public static fun getLowerBound-impl (Lkotlin/ranges/ClosedFloatingPointRange;I)Ljava/lang/Double; - public static fun getLowerBound-impl (Lkotlin/ranges/ClosedFloatingPointRange;ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double; - public final fun getRange ()Lkotlin/ranges/ClosedFloatingPointRange; - public fun getUpperBound (I)Ljava/lang/Double; - public fun getUpperBound (ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double; - public static fun getUpperBound-impl (Lkotlin/ranges/ClosedFloatingPointRange;I)Ljava/lang/Double; - public static fun getUpperBound-impl (Lkotlin/ranges/ClosedFloatingPointRange;ILspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double; - public fun hashCode ()I - public static fun hashCode-impl (Lkotlin/ranges/ClosedFloatingPointRange;)I - public fun nearestInDomain (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun nearestInDomain-impl (Lkotlin/ranges/ClosedFloatingPointRange;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Lkotlin/ranges/ClosedFloatingPointRange;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Lkotlin/ranges/ClosedFloatingPointRange; - public fun volume ()D - public static fun volume-impl (Lkotlin/ranges/ClosedFloatingPointRange;)D -} - public abstract interface class space/kscience/kmath/expressions/AutoDiffProcessor { public abstract fun process (Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/DifferentiableExpression; } @@ -179,9 +115,6 @@ public class space/kscience/kmath/expressions/FunctionalExpressionExtendedField public fun cosh (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; public fun exp (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; public fun ln (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; @@ -190,8 +123,6 @@ public class space/kscience/kmath/expressions/FunctionalExpressionExtendedField public fun pow (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sin (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; @@ -206,17 +137,31 @@ public class space/kscience/kmath/expressions/FunctionalExpressionExtendedField public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } -public class space/kscience/kmath/expressions/FunctionalExpressionField : space/kscience/kmath/expressions/FunctionalExpressionRing, space/kscience/kmath/operations/Field { +public class space/kscience/kmath/expressions/FunctionalExpressionField : space/kscience/kmath/expressions/FunctionalExpressionRing, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/ScaleOperations { public fun (Lspace/kscience/kmath/operations/Field;)V public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Ljava/lang/Number;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public final fun div (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; + public fun div (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; public final fun div (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression; public fun div (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; + public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; + public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; + public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; + public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/expressions/Expression;D)Lspace/kscience/kmath/expressions/Expression; + public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun times (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -239,24 +184,16 @@ public class space/kscience/kmath/expressions/FunctionalExpressionSpace : space/ public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/expressions/Expression; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public final fun minus (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public final fun minus (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression; public fun minus (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public final fun plus (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public final fun plus (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression; public fun plus (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; @@ -272,7 +209,7 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffExpression : s public fun invoke (Ljava/util/Map;)Ljava/lang/Object; } -public final class space/kscience/kmath/expressions/SimpleAutoDiffExtendedField : space/kscience/kmath/expressions/SimpleAutoDiffField, space/kscience/kmath/operations/ExtendedField { +public final class space/kscience/kmath/expressions/SimpleAutoDiffExtendedField : space/kscience/kmath/expressions/SimpleAutoDiffField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/ScaleOperations { public fun (Lspace/kscience/kmath/operations/ExtendedField;Ljava/util/Map;)V public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; public fun acos (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; @@ -294,12 +231,16 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffExtendedField public fun exp (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; public fun ln (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun pow (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; public final fun pow (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/expressions/AutoDiffValue;D)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sin (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; @@ -314,7 +255,7 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffExtendedField public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } -public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscience/kmath/expressions/ExpressionAlgebra, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/RingWithNumbers { +public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscience/kmath/expressions/ExpressionAlgebra, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumbersAddOperations { public fun (Lspace/kscience/kmath/operations/Field;Ljava/util/Map;)V public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; @@ -329,8 +270,6 @@ public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscien public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/AutoDiffValue; public final fun const (Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/AutoDiffValue; public final fun derive (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Ljava/lang/Number;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun div (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; @@ -352,9 +291,7 @@ public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscien public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; public fun minus (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; public fun multiply (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; @@ -367,6 +304,8 @@ public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscien public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/expressions/AutoDiffValue;D)Lspace/kscience/kmath/expressions/AutoDiffValue; public final fun setD (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Object;)V public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; @@ -521,8 +460,6 @@ public final class space/kscience/kmath/linear/BufferMatrixContext : space/kscie public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; @@ -530,21 +467,14 @@ public final class space/kscience/kmath/linear/BufferMatrixContext : space/kscie public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun multiply (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public final fun one (II)Lspace/kscience/kmath/nd/Structure2D; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public fun point (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; public fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; @@ -561,7 +491,7 @@ public final class space/kscience/kmath/linear/BufferMatrixContext$Companion { } public final class space/kscience/kmath/linear/BufferVectorSpace : space/kscience/kmath/linear/VectorSpace { - public fun (ILspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function2;)V + public fun (ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -569,24 +499,17 @@ public final class space/kscience/kmath/linear/BufferVectorSpace : space/kscienc public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; + public fun getAlgebra ()Lspace/kscience/kmath/operations/Ring; public final fun getBufferFactory ()Lkotlin/jvm/functions/Function2; public fun getSize ()I - public fun getSpace ()Lspace/kscience/kmath/operations/Space; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/structures/Buffer; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; + public fun scale (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; @@ -617,7 +540,6 @@ public abstract interface class space/kscience/kmath/linear/GenericMatrixContext public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public abstract fun getElementContext ()Lspace/kscience/kmath/operations/Ring; public abstract fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun multiply (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public abstract fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; public abstract fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; } @@ -627,16 +549,12 @@ public final class space/kscience/kmath/linear/GenericMatrixContext$DefaultImpls public static fun binaryOperation (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun binaryOperationFunction (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D; - public static fun div (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public static fun dot (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun dot (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static fun minus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun multiply (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public static fun plus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun point (Lspace/kscience/kmath/linear/GenericMatrixContext;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; - public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; public static fun unaryMinus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun unaryOperation (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; @@ -727,14 +645,10 @@ public final class space/kscience/kmath/linear/MatrixContext$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun binaryOperationFunction (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D; - public static fun div (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public static fun minus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun plus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun point (Lspace/kscience/kmath/linear/MatrixContext;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; - public static fun times (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun times (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun times (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; - public static fun unaryMinus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun unaryOperation (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun unaryOperationFunction (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; @@ -792,15 +706,11 @@ public final class space/kscience/kmath/linear/RealMatrixContext : space/kscienc public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/linear/BufferMatrix; public final fun one (II)Lspace/kscience/kmath/nd/Structure2D; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; @@ -808,12 +718,8 @@ public final class space/kscience/kmath/linear/RealMatrixContext : space/kscienc public fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/Structure2D; public fun times (DLspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public fun times (Lspace/kscience/kmath/nd/Structure2D;D)Lspace/kscience/kmath/linear/BufferMatrix; - public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public synthetic fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; public final fun toBufferMatrix (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; @@ -852,16 +758,17 @@ public final class space/kscience/kmath/linear/UnitFeature : space/kscience/kmat public abstract interface class space/kscience/kmath/linear/VectorSpace : space/kscience/kmath/operations/Space { public static final field Companion Lspace/kscience/kmath/linear/VectorSpace$Companion; public abstract fun add (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun getAlgebra ()Lspace/kscience/kmath/operations/Ring; public abstract fun getSize ()I - public abstract fun getSpace ()Lspace/kscience/kmath/operations/Space; public abstract fun getZero ()Lspace/kscience/kmath/structures/Buffer; - public abstract fun multiply (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun scale (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; } public final class space/kscience/kmath/linear/VectorSpace$Companion { - public final fun buffered (ILspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferVectorSpace; - public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/VectorSpace$Companion;ILspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/BufferVectorSpace; + public final fun buffered (ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferVectorSpace; + public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/VectorSpace$Companion;ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/BufferVectorSpace; public final fun real (I)Lspace/kscience/kmath/linear/BufferVectorSpace; } @@ -870,13 +777,10 @@ public final class space/kscience/kmath/linear/VectorSpace$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static fun binaryOperationFunction (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; - public static fun div (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public static fun getZero (Lspace/kscience/kmath/linear/VectorSpace;)Lspace/kscience/kmath/structures/Buffer; public static fun minus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun multiply (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public static fun plus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun times (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun times (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; + public static fun scale (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; public static fun unaryMinus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static fun unaryOperation (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static fun unaryOperationFunction (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; @@ -956,14 +860,28 @@ public final class space/kscience/kmath/nd/BufferNDAlgebraKt { public class space/kscience/kmath/nd/BufferedNDField : space/kscience/kmath/nd/BufferedNDRing, space/kscience/kmath/nd/NDField { public fun ([ILspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;)V public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public fun div (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/nd/NDStructure;D)Lspace/kscience/kmath/nd/NDStructure; + public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; } public class space/kscience/kmath/nd/BufferedNDRing : space/kscience/kmath/nd/BufferedNDSpace, space/kscience/kmath/nd/NDRing { @@ -990,11 +908,9 @@ public class space/kscience/kmath/nd/BufferedNDSpace : space/kscience/kmath/nd/B public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure; public fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public fun getBuffer (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/structures/Buffer; public final fun getBufferFactory ()Lkotlin/jvm/functions/Function2; - public synthetic fun getElementContext ()Ljava/lang/Object; + public synthetic fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; public final fun getElementContext ()Lspace/kscience/kmath/operations/Space; public final fun getShape ()[I public fun getStrides ()Lspace/kscience/kmath/nd/Strides; @@ -1009,18 +925,12 @@ public class space/kscience/kmath/nd/BufferedNDSpace : space/kscience/kmath/nd/B public fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public fun minus (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public fun plus (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; @@ -1065,7 +975,7 @@ public final class space/kscience/kmath/nd/MutableNDStructure$DefaultImpls { public abstract interface class space/kscience/kmath/nd/NDAlgebra { public static final field Companion Lspace/kscience/kmath/nd/NDAlgebra$Companion; public abstract fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun getElementContext ()Ljava/lang/Object; + public abstract fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; public abstract fun getShape ()[I public abstract fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public abstract fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure; @@ -1093,7 +1003,7 @@ public class space/kscience/kmath/nd/NDBuffer : space/kscience/kmath/nd/NDStruct public fun toString ()Ljava/lang/String; } -public abstract interface class space/kscience/kmath/nd/NDField : space/kscience/kmath/nd/NDRing, space/kscience/kmath/operations/Field { +public abstract interface class space/kscience/kmath/nd/NDField : space/kscience/kmath/nd/NDRing, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/ScaleOperations { public abstract fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public abstract fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public abstract fun divide (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; @@ -1104,27 +1014,29 @@ public final class space/kscience/kmath/nd/NDField$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure; - public static fun div (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun div (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun div (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public static fun div (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public static fun div (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun divide (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun invoke (Lspace/kscience/kmath/nd/NDField;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public static fun leftSideNumberOperation (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun minus (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun minus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public static fun minus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun multiply (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public static fun multiply (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public static fun number (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public static fun plus (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun plus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public static fun plus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public static fun rightSideNumberOperation (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun times (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun times (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun times (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public static fun times (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public static fun times (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun unaryMinus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun unaryOperation (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; @@ -1145,22 +1057,17 @@ public final class space/kscience/kmath/nd/NDRing$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure; - public static fun div (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public static fun invoke (Lspace/kscience/kmath/nd/NDRing;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun minus (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun minus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public static fun minus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun multiply (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public static fun multiply (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun plus (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun plus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public static fun plus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun times (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun times (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun times (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public static fun times (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public static fun times (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun unaryMinus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun unaryOperation (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; @@ -1171,7 +1078,6 @@ public abstract interface class space/kscience/kmath/nd/NDSpace : space/kscience public abstract fun add (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public abstract fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun multiply (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public abstract fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; } @@ -1184,18 +1090,13 @@ public final class space/kscience/kmath/nd/NDSpace$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure; - public static fun div (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public static fun invoke (Lspace/kscience/kmath/nd/NDSpace;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun minus (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun minus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public static fun minus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun multiply (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public static fun plus (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun plus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public static fun plus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun times (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun times (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; - public static fun unaryMinus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun unaryOperation (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; @@ -1230,7 +1131,7 @@ public final class space/kscience/kmath/nd/NDStructureKt { public static final fun mapInPlace (Lspace/kscience/kmath/nd/MutableNDStructure;Lkotlin/jvm/functions/Function2;)V } -public final class space/kscience/kmath/nd/RealNDField : space/kscience/kmath/nd/BufferedNDField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/RingWithNumbers { +public final class space/kscience/kmath/nd/RealNDField : space/kscience/kmath/nd/BufferedNDField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { public fun ([I)V public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; public fun acos (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; @@ -1258,9 +1159,6 @@ public final class space/kscience/kmath/nd/RealNDField : space/kscience/kmath/nd public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; public fun ln (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; public fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; @@ -1273,6 +1171,7 @@ public final class space/kscience/kmath/nd/RealNDField : space/kscience/kmath/nd public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; @@ -1283,9 +1182,9 @@ public final class space/kscience/kmath/nd/RealNDField : space/kscience/kmath/nd public fun power (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/nd/NDStructure;D)Lspace/kscience/kmath/nd/NDStructure; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sin (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; @@ -1310,7 +1209,7 @@ public final class space/kscience/kmath/nd/ShapeMismatchException : java/lang/Ru public final fun getExpected ()[I } -public final class space/kscience/kmath/nd/ShortNDRing : space/kscience/kmath/nd/BufferedNDRing, space/kscience/kmath/operations/RingWithNumbers { +public final class space/kscience/kmath/nd/ShortNDRing : space/kscience/kmath/nd/BufferedNDRing, space/kscience/kmath/operations/NumbersAddOperations { public fun ([I)V public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer; @@ -1420,12 +1319,8 @@ public abstract interface class space/kscience/kmath/operations/AlgebraElement { } public final class space/kscience/kmath/operations/AlgebraElementsKt { - public static final fun div (Lspace/kscience/kmath/operations/AlgebraElement;Ljava/lang/Number;)Lspace/kscience/kmath/operations/AlgebraElement; public static final fun div (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement; - public static final fun minus (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement; public static final fun plus (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement; - public static final fun times (Ljava/lang/Number;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement; - public static final fun times (Lspace/kscience/kmath/operations/AlgebraElement;Ljava/lang/Number;)Lspace/kscience/kmath/operations/AlgebraElement; public static final fun times (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement; } @@ -1481,7 +1376,7 @@ public final class space/kscience/kmath/operations/BigInt$Companion { public final fun getZERO ()Lspace/kscience/kmath/operations/BigInt; } -public final class space/kscience/kmath/operations/BigIntField : space/kscience/kmath/operations/Field, space/kscience/kmath/operations/RingWithNumbers { +public final class space/kscience/kmath/operations/BigIntField : space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { public static final field INSTANCE Lspace/kscience/kmath/operations/BigIntField; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; @@ -1490,8 +1385,6 @@ public final class space/kscience/kmath/operations/BigIntField : space/kscience/ public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/operations/BigInt; - public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Ljava/lang/Number;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun div (Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt; @@ -1511,9 +1404,7 @@ public final class space/kscience/kmath/operations/BigIntField : space/kscience/ public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt; public fun minus (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt; public fun multiply (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt; @@ -1526,6 +1417,8 @@ public final class space/kscience/kmath/operations/BigIntField : space/kscience/ public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/operations/BigInt;D)Lspace/kscience/kmath/operations/BigInt; public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public fun times (Ljava/lang/Number;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; @@ -1565,8 +1458,6 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Byte; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun div (BLjava/lang/Number;)Ljava/lang/Byte; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun getOne ()Ljava/lang/Byte; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Byte; @@ -1577,8 +1468,6 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma public fun minus (BB)Ljava/lang/Byte; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (BB)Ljava/lang/Byte; - public fun multiply (BLjava/lang/Number;)Ljava/lang/Byte; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun norm (B)Ljava/lang/Byte; public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object; @@ -1590,10 +1479,6 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun times (BB)Ljava/lang/Byte; - public fun times (BLjava/lang/Number;)Ljava/lang/Byte; - public fun times (Ljava/lang/Number;B)Ljava/lang/Byte; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (B)Ljava/lang/Byte; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; @@ -1605,16 +1490,34 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma } public abstract interface class space/kscience/kmath/operations/ExponentialOperations : space/kscience/kmath/operations/Algebra { + public static final field ACOSH_OPERATION Ljava/lang/String; + public static final field ASINH_OPERATION Ljava/lang/String; + public static final field ATANH_OPERATION Ljava/lang/String; + public static final field COSH_OPERATION Ljava/lang/String; public static final field Companion Lspace/kscience/kmath/operations/ExponentialOperations$Companion; public static final field EXP_OPERATION Ljava/lang/String; public static final field LN_OPERATION Ljava/lang/String; + public static final field SINH_OPERATION Ljava/lang/String; + public static final field TANH_OPERATION Ljava/lang/String; + public abstract fun acosh (Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun asinh (Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun atanh (Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun exp (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun ln (Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun sinh (Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun tanh (Ljava/lang/Object;)Ljava/lang/Object; } public final class space/kscience/kmath/operations/ExponentialOperations$Companion { + public static final field ACOSH_OPERATION Ljava/lang/String; + public static final field ASINH_OPERATION Ljava/lang/String; + public static final field ATANH_OPERATION Ljava/lang/String; + public static final field COSH_OPERATION Ljava/lang/String; public static final field EXP_OPERATION Ljava/lang/String; public static final field LN_OPERATION Ljava/lang/String; + public static final field SINH_OPERATION Ljava/lang/String; + public static final field TANH_OPERATION Ljava/lang/String; } public final class space/kscience/kmath/operations/ExponentialOperations$DefaultImpls { @@ -1625,7 +1528,7 @@ public final class space/kscience/kmath/operations/ExponentialOperations$Default public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } -public abstract interface class space/kscience/kmath/operations/ExtendedField : space/kscience/kmath/operations/ExtendedFieldOperations, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra { +public abstract interface class space/kscience/kmath/operations/ExtendedField : space/kscience/kmath/operations/ExtendedFieldOperations, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/ScaleOperations { public abstract fun acosh (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun asinh (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun atanh (Ljava/lang/Object;)Ljava/lang/Object; @@ -1643,12 +1546,12 @@ public final class space/kscience/kmath/operations/ExtendedField$DefaultImpls { public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Ljava/lang/Object; public static fun cosh (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun minus (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun number (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Number;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun pow (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; @@ -1660,13 +1563,12 @@ public final class space/kscience/kmath/operations/ExtendedField$DefaultImpls { public static fun times (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public static fun times (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun times (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryMinus (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; } -public abstract interface class space/kscience/kmath/operations/ExtendedFieldOperations : space/kscience/kmath/operations/ExponentialOperations, space/kscience/kmath/operations/FieldOperations, space/kscience/kmath/operations/HyperbolicOperations, space/kscience/kmath/operations/PowerOperations, space/kscience/kmath/operations/TrigonometricOperations { +public abstract interface class space/kscience/kmath/operations/ExtendedFieldOperations : space/kscience/kmath/operations/ExponentialOperations, space/kscience/kmath/operations/FieldOperations, space/kscience/kmath/operations/PowerOperations, space/kscience/kmath/operations/TrigonometricOperations { public abstract fun tan (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun tanh (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; @@ -1676,7 +1578,6 @@ public final class space/kscience/kmath/operations/ExtendedFieldOperations$Defau public static fun binaryOperation (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun minus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -1684,32 +1585,32 @@ public final class space/kscience/kmath/operations/ExtendedFieldOperations$Defau public static fun sqrt (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object; public static fun tan (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object; public static fun tanh (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun times (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryMinus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object; } -public abstract interface class space/kscience/kmath/operations/Field : space/kscience/kmath/operations/FieldOperations, space/kscience/kmath/operations/Ring { - public abstract fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; +public abstract interface class space/kscience/kmath/operations/Field : space/kscience/kmath/operations/FieldOperations, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring, space/kscience/kmath/operations/ScaleOperations { + public abstract fun number (Ljava/lang/Number;)Ljava/lang/Object; } public final class space/kscience/kmath/operations/Field$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/Field;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun minus (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun number (Lspace/kscience/kmath/operations/Field;Ljava/lang/Number;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun times (Lspace/kscience/kmath/operations/Field;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public static fun times (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun times (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryMinus (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;)Ljava/lang/Object; @@ -1731,14 +1632,10 @@ public final class space/kscience/kmath/operations/FieldOperations$DefaultImpls public static fun binaryOperation (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun minus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun times (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryMinus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;)Ljava/lang/Object; @@ -1771,8 +1668,6 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun div (FF)Ljava/lang/Float; public fun div (FLjava/lang/Number;)Ljava/lang/Float; - public fun div (Ljava/lang/Number;F)Ljava/lang/Float; - public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (FF)Ljava/lang/Float; @@ -1791,8 +1686,6 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k public fun minus (FF)Ljava/lang/Float; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (FF)Ljava/lang/Float; - public fun multiply (FLjava/lang/Number;)Ljava/lang/Float; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun norm (F)Ljava/lang/Float; public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object; @@ -1807,6 +1700,8 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k public fun rightSideNumberOperation (Ljava/lang/String;FLjava/lang/Number;)Ljava/lang/Float; public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public fun scale (FD)Ljava/lang/Float; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun sin (F)Ljava/lang/Float; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh (F)Ljava/lang/Float; @@ -1832,39 +1727,6 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; } -public abstract interface class space/kscience/kmath/operations/HyperbolicOperations : space/kscience/kmath/operations/Algebra { - public static final field ACOSH_OPERATION Ljava/lang/String; - public static final field ASINH_OPERATION Ljava/lang/String; - public static final field ATANH_OPERATION Ljava/lang/String; - public static final field COSH_OPERATION Ljava/lang/String; - public static final field Companion Lspace/kscience/kmath/operations/HyperbolicOperations$Companion; - public static final field SINH_OPERATION Ljava/lang/String; - public static final field TANH_OPERATION Ljava/lang/String; - public abstract fun acosh (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun asinh (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun cosh (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun tanh (Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class space/kscience/kmath/operations/HyperbolicOperations$Companion { - public static final field ACOSH_OPERATION Ljava/lang/String; - public static final field ASINH_OPERATION Ljava/lang/String; - public static final field ATANH_OPERATION Ljava/lang/String; - public static final field COSH_OPERATION Ljava/lang/String; - public static final field SINH_OPERATION Ljava/lang/String; - public static final field TANH_OPERATION Ljava/lang/String; -} - -public final class space/kscience/kmath/operations/HyperbolicOperations$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/HyperbolicOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/HyperbolicOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/HyperbolicOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/HyperbolicOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/HyperbolicOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; -} - public final class space/kscience/kmath/operations/IntRing : space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring { public static final field INSTANCE Lspace/kscience/kmath/operations/IntRing; public fun add (II)Ljava/lang/Integer; @@ -1874,8 +1736,6 @@ public final class space/kscience/kmath/operations/IntRing : space/kscience/kmat public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Integer; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun div (ILjava/lang/Number;)Ljava/lang/Integer; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun getOne ()Ljava/lang/Integer; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Integer; @@ -1886,8 +1746,6 @@ public final class space/kscience/kmath/operations/IntRing : space/kscience/kmat public fun minus (II)Ljava/lang/Integer; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (II)Ljava/lang/Integer; - public fun multiply (ILjava/lang/Number;)Ljava/lang/Integer; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun norm (I)Ljava/lang/Integer; public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object; @@ -1899,10 +1757,6 @@ public final class space/kscience/kmath/operations/IntRing : space/kscience/kmat public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun times (II)Ljava/lang/Integer; - public fun times (ILjava/lang/Number;)Ljava/lang/Integer; - public fun times (Ljava/lang/Number;I)Ljava/lang/Integer; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (I)Ljava/lang/Integer; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; @@ -1923,7 +1777,7 @@ public final class space/kscience/kmath/operations/JBigDecimalField : space/ksci public final class space/kscience/kmath/operations/JBigDecimalField$Companion : space/kscience/kmath/operations/JBigDecimalFieldBase { } -public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/PowerOperations { +public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/PowerOperations, space/kscience/kmath/operations/ScaleOperations { public fun ()V public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; @@ -1932,8 +1786,6 @@ public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : spa public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Ljava/math/BigDecimal; - public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Ljava/lang/Number;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun div (Ljava/math/BigDecimal;Ljava/lang/Number;)Ljava/math/BigDecimal; @@ -1949,9 +1801,7 @@ public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : spa public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (Ljava/math/BigDecimal;Ljava/lang/Number;)Ljava/math/BigDecimal; public fun multiply (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Ljava/math/BigDecimal; @@ -1964,6 +1814,8 @@ public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : spa public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun rightSideNumberOperation (Ljava/lang/String;Ljava/math/BigDecimal;Ljava/lang/Number;)Ljava/math/BigDecimal; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Ljava/math/BigDecimal;D)Ljava/math/BigDecimal; public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; public fun sqrt (Ljava/math/BigDecimal;)Ljava/math/BigDecimal; public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; @@ -1981,7 +1833,7 @@ public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : spa public fun unaryPlus (Ljava/math/BigDecimal;)Ljava/math/BigDecimal; } -public final class space/kscience/kmath/operations/JBigIntegerField : space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra { +public final class space/kscience/kmath/operations/JBigIntegerField : space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring { public static final field INSTANCE Lspace/kscience/kmath/operations/JBigIntegerField; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger; @@ -1990,14 +1842,6 @@ public final class space/kscience/kmath/operations/JBigIntegerField : space/ksci public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Ljava/math/BigInteger; - public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Ljava/lang/Number;Ljava/math/BigInteger;)Ljava/math/BigInteger; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Ljava/math/BigInteger;Ljava/lang/Number;)Ljava/math/BigInteger; - public fun div (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger; - public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun divide (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Ljava/math/BigInteger; public synthetic fun getZero ()Ljava/lang/Object; @@ -2007,9 +1851,7 @@ public final class space/kscience/kmath/operations/JBigIntegerField : space/ksci public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (Ljava/math/BigInteger;Ljava/lang/Number;)Ljava/math/BigInteger; public fun multiply (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Ljava/math/BigInteger; @@ -2018,11 +1860,7 @@ public final class space/kscience/kmath/operations/JBigIntegerField : space/ksci public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun rightSideNumberOperation (Ljava/lang/String;Ljava/math/BigInteger;Ljava/lang/Number;)Ljava/math/BigInteger; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Ljava/math/BigInteger;)Ljava/math/BigInteger; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/math/BigInteger;Ljava/lang/Number;)Ljava/math/BigInteger; public fun times (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Ljava/math/BigInteger;)Ljava/math/BigInteger; @@ -2045,8 +1883,6 @@ public final class space/kscience/kmath/operations/LongRing : space/kscience/kma public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Long; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun div (JLjava/lang/Number;)Ljava/lang/Long; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun getOne ()Ljava/lang/Long; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Long; @@ -2057,8 +1893,6 @@ public final class space/kscience/kmath/operations/LongRing : space/kscience/kma public fun minus (JJ)Ljava/lang/Long; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (JJ)Ljava/lang/Long; - public fun multiply (JLjava/lang/Number;)Ljava/lang/Long; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun norm (J)Ljava/lang/Long; public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object; @@ -2070,10 +1904,6 @@ public final class space/kscience/kmath/operations/LongRing : space/kscience/kma public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun times (JJ)Ljava/lang/Long; - public fun times (JLjava/lang/Number;)Ljava/lang/Long; - public fun times (Ljava/lang/Number;J)Ljava/lang/Long; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (J)Ljava/lang/Long; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; @@ -2088,6 +1918,25 @@ public abstract interface class space/kscience/kmath/operations/Norm { public abstract fun norm (Ljava/lang/Object;)Ljava/lang/Object; } +public final class space/kscience/kmath/operations/NumbersAddOperations$DefaultImpls { + public static fun binaryOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public static fun bindSymbol (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Ljava/lang/Object; + public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public static fun minus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public static fun minus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public static fun minus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun plus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public static fun plus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public static fun plus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public static fun unaryOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public static fun unaryPlus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;)Ljava/lang/Object; +} + public abstract interface class space/kscience/kmath/operations/NumericAlgebra : space/kscience/kmath/operations/Algebra { public abstract fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; @@ -2135,7 +1984,7 @@ public final class space/kscience/kmath/operations/PowerOperations$DefaultImpls public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } -public final class space/kscience/kmath/operations/RealField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/Norm { +public final class space/kscience/kmath/operations/RealField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/ScaleOperations { public static final field INSTANCE Lspace/kscience/kmath/operations/RealField; public fun acos (D)Ljava/lang/Double; public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; @@ -2162,8 +2011,6 @@ public final class space/kscience/kmath/operations/RealField : space/kscience/km public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun div (DD)Ljava/lang/Double; public fun div (DLjava/lang/Number;)Ljava/lang/Double; - public fun div (Ljava/lang/Number;D)Ljava/lang/Double; - public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (DD)Ljava/lang/Double; @@ -2182,8 +2029,6 @@ public final class space/kscience/kmath/operations/RealField : space/kscience/km public fun minus (DD)Ljava/lang/Double; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (DD)Ljava/lang/Double; - public fun multiply (DLjava/lang/Number;)Ljava/lang/Double; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun norm (D)Ljava/lang/Double; public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object; @@ -2198,6 +2043,8 @@ public final class space/kscience/kmath/operations/RealField : space/kscience/km public fun rightSideNumberOperation (Ljava/lang/String;DLjava/lang/Number;)Ljava/lang/Double; public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public fun scale (DD)Ljava/lang/Double; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun sin (D)Ljava/lang/Double; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh (D)Ljava/lang/Double; @@ -2231,13 +2078,9 @@ public final class space/kscience/kmath/operations/Ring$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun minus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun times (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryMinus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;)Ljava/lang/Object; @@ -2259,41 +2102,30 @@ public final class space/kscience/kmath/operations/RingOperations$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun minus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun times (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryMinus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;)Ljava/lang/Object; } -public final class space/kscience/kmath/operations/RingWithNumbers$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun minus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun minus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun minus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun number (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Number;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun times (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryMinus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/operations/RingWithNumbers;Ljava/lang/Object;)Ljava/lang/Object; +public abstract interface class space/kscience/kmath/operations/ScaleOperations : space/kscience/kmath/operations/Algebra { + public abstract fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public abstract fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public abstract fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/operations/ScaleOperations$DefaultImpls { + public static fun binaryOperation (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public static fun bindSymbol (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Ljava/lang/Object; + public static fun div (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public static fun times (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public static fun times (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public static fun unaryOperation (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } public final class space/kscience/kmath/operations/ShortRing : space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring { @@ -2305,8 +2137,6 @@ public final class space/kscience/kmath/operations/ShortRing : space/kscience/km public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Short; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun div (SLjava/lang/Number;)Ljava/lang/Short; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Ljava/lang/Short; public synthetic fun getZero ()Ljava/lang/Object; @@ -2316,9 +2146,7 @@ public final class space/kscience/kmath/operations/ShortRing : space/kscience/km public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (SS)Ljava/lang/Short; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (SLjava/lang/Number;)Ljava/lang/Short; public fun multiply (SS)Ljava/lang/Short; public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object; public fun norm (S)Ljava/lang/Short; @@ -2329,11 +2157,7 @@ public final class space/kscience/kmath/operations/ShortRing : space/kscience/km public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun rightSideNumberOperation (Ljava/lang/String;SLjava/lang/Number;)Ljava/lang/Short; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;S)Ljava/lang/Short; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (SLjava/lang/Number;)Ljava/lang/Short; public fun times (SS)Ljava/lang/Short; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (S)Ljava/lang/Short; @@ -2352,12 +2176,8 @@ public final class space/kscience/kmath/operations/Space$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun minus (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/Space;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun unaryMinus (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;)Ljava/lang/Object; @@ -2369,12 +2189,8 @@ public abstract interface class space/kscience/kmath/operations/SpaceOperations public static final field PLUS_OPERATION Ljava/lang/String; public abstract fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public abstract fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public abstract fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public abstract fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public abstract fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public abstract fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; @@ -2389,12 +2205,8 @@ public final class space/kscience/kmath/operations/SpaceOperations$DefaultImpls public static fun binaryOperation (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun minus (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun unaryMinus (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;)Ljava/lang/Object; @@ -2776,8 +2588,6 @@ public final class space/kscience/kmath/structures/RealBufferField : space/kscie public fun cos-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun cosh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun div (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; @@ -2798,9 +2608,7 @@ public final class space/kscience/kmath/structures/RealBufferField : space/kscie public fun ln-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D public fun multiply-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; @@ -2813,6 +2621,8 @@ public final class space/kscience/kmath/structures/RealBufferField : space/kscie public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;D)[D public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sin-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; @@ -2863,9 +2673,7 @@ public final class space/kscience/kmath/structures/RealBufferFieldOperations : s public fun cos-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun cosh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public fun div (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D @@ -2875,9 +2683,7 @@ public final class space/kscience/kmath/structures/RealBufferFieldOperations : s public fun ln-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D public fun multiply-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; @@ -2895,14 +2701,10 @@ public final class space/kscience/kmath/structures/RealBufferFieldOperations : s public fun tan-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; public fun tanh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public fun times (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun unaryMinus-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt index 3d0c6d3b8..c948f8672 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt @@ -16,8 +16,8 @@ package space.kscience.kmath.domains import space.kscience.kmath.linear.Point +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.indices /** @@ -26,6 +26,7 @@ import space.kscience.kmath.structures.indices * * @author Alexander Nozik */ +@UnstableKMathAPI public class HyperSquareDomain(private val lower: Buffer, private val upper: Buffer) : RealDomain { public override val dimension: Int get() = lower.size @@ -33,26 +34,10 @@ public class HyperSquareDomain(private val lower: Buffer, private val up point[i] in lower[i]..upper[i] } - public override fun getLowerBound(num: Int, point: Point): Double = lower[num] - public override fun getLowerBound(num: Int): Double = lower[num] - public override fun getUpperBound(num: Int, point: Point): Double = upper[num] - public override fun getUpperBound(num: Int): Double = upper[num] - public override fun nearestInDomain(point: Point): Point { - val res = DoubleArray(point.size) { i -> - when { - point[i] < lower[i] -> lower[i] - point[i] > upper[i] -> upper[i] - else -> point[i] - } - } - - return RealBuffer(*res) - } - public override fun volume(): Double { var res = 1.0 diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt index 13555dad9..c20cbfec1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt @@ -15,45 +15,27 @@ */ package space.kscience.kmath.domains -import space.kscience.kmath.linear.Point +import space.kscience.kmath.misc.UnstableKMathAPI /** * n-dimensional volume * * @author Alexander Nozik */ +@UnstableKMathAPI public interface RealDomain : Domain { - public fun nearestInDomain(point: Point): Point - - /** - * The lower edge for the domain going down from point - * @param num - * @param point - * @return - */ - public fun getLowerBound(num: Int, point: Point): Double? - - /** - * The upper edge of the domain going up from point - * @param num - * @param point - * @return - */ - public fun getUpperBound(num: Int, point: Point): Double? /** * Global lower edge - * @param num - * @return + * @param num axis number */ - public fun getLowerBound(num: Int): Double? + public fun getLowerBound(num: Int): Double /** * Global upper edge - * @param num - * @return + * @param num axis number */ - public fun getUpperBound(num: Int): Double? + public fun getUpperBound(num: Int): Double /** * Hyper volume diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt index f1bcc50ad..002caac50 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt @@ -16,19 +16,15 @@ package space.kscience.kmath.domains import space.kscience.kmath.linear.Point +import space.kscience.kmath.misc.UnstableKMathAPI +@UnstableKMathAPI public class UnconstrainedDomain(public override val dimension: Int) : RealDomain { public override operator fun contains(point: Point): Boolean = true - public override fun getLowerBound(num: Int, point: Point): Double? = Double.NEGATIVE_INFINITY + public override fun getLowerBound(num: Int): Double = Double.NEGATIVE_INFINITY - public override fun getLowerBound(num: Int): Double? = Double.NEGATIVE_INFINITY - - public override fun getUpperBound(num: Int, point: Point): Double? = Double.POSITIVE_INFINITY - - public override fun getUpperBound(num: Int): Double? = Double.POSITIVE_INFINITY - - public override fun nearestInDomain(point: Point): Point = point + public override fun getUpperBound(num: Int): Double = Double.POSITIVE_INFINITY public override fun volume(): Double = Double.POSITIVE_INFINITY } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt index 36cd4afa7..d20349960 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt @@ -1,11 +1,11 @@ package space.kscience.kmath.domains import space.kscience.kmath.linear.Point -import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.misc.UnstableKMathAPI +@UnstableKMathAPI public inline class UnivariateDomain(public val range: ClosedFloatingPointRange) : RealDomain { - public override val dimension: Int - get() = 1 + public override val dimension: Int get() = 1 public operator fun contains(d: Double): Boolean = range.contains(d) @@ -14,33 +14,12 @@ public inline class UnivariateDomain(public val range: ClosedFloatingPointRange< return contains(point[0]) } - public override fun nearestInDomain(point: Point): Point { - require(point.size == 1) - val value = point[0] - - return when { - value in range -> point - value >= range.endInclusive -> doubleArrayOf(range.endInclusive).asBuffer() - else -> doubleArrayOf(range.start).asBuffer() - } - } - - public override fun getLowerBound(num: Int, point: Point): Double? { + public override fun getLowerBound(num: Int): Double { require(num == 0) return range.start } - public override fun getUpperBound(num: Int, point: Point): Double? { - require(num == 0) - return range.endInclusive - } - - public override fun getLowerBound(num: Int): Double? { - require(num == 0) - return range.start - } - - public override fun getUpperBound(num: Int): Double? { + public override fun getUpperBound(num: Int): Double { require(num == 0) return range.endInclusive } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index 5177bc868..3c23d0ecf 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -48,18 +48,21 @@ public open class FunctionalExpressionSpace>( ) : FunctionalExpressionAlgebra(algebra), Space> { public override val zero: Expression get() = const(algebra.zero) + override fun Expression.unaryMinus(): Expression = + unaryOperation(SpaceOperations.MINUS_OPERATION, this) + /** * Builds an Expression of addition of two another expressions. */ public override fun add(a: Expression, b: Expression): Expression = - binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b) + binaryOperation(SpaceOperations.PLUS_OPERATION, a, b) - /** - * Builds an Expression of multiplication of expression by number. - */ - public override fun multiply(a: Expression, k: Number): Expression = Expression { arguments -> - algebra.multiply(a.invoke(arguments), k) - } +// /** +// * Builds an Expression of multiplication of expression by number. +// */ +// public override fun multiply(a: Expression, k: Number): Expression = Expression { arguments -> +// algebra.multiply(a.invoke(arguments), k) +// } public operator fun Expression.plus(arg: T): Expression = this + const(arg) public operator fun Expression.minus(arg: T): Expression = this - const(arg) @@ -71,13 +74,13 @@ public open class FunctionalExpressionSpace>( public override fun binaryOperationFunction(operation: String): (left: Expression, right: Expression) -> Expression = super.binaryOperationFunction(operation) + } public open class FunctionalExpressionRing>( algebra: A, ) : FunctionalExpressionSpace(algebra), Ring> { - public override val one: Expression - get() = const(algebra.one) + public override val one: Expression get() = const(algebra.one) /** * Builds an Expression of multiplication of two expressions. @@ -95,9 +98,10 @@ public open class FunctionalExpressionRing>( super.binaryOperationFunction(operation) } -public open class FunctionalExpressionField>( +public open class FunctionalExpressionField>( algebra: A, -) : FunctionalExpressionRing(algebra), Field> { +) : FunctionalExpressionRing(algebra), Field>, + ScaleOperations> { /** * Builds an Expression of division an expression by another one. */ @@ -112,6 +116,10 @@ public open class FunctionalExpressionField>( public override fun binaryOperationFunction(operation: String): (left: Expression, right: Expression) -> Expression = super.binaryOperationFunction(operation) + + override fun scale(a: Expression, value: Double): Expression = algebra { + Expression { args -> a(args) * value } + } } public open class FunctionalExpressionExtendedField>( @@ -160,5 +168,6 @@ public inline fun > A.expressionInRing(block: FunctionalExpressio public inline fun > A.expressionInField(block: FunctionalExpressionField.() -> Expression): Expression = FunctionalExpressionField(this).block() -public inline fun > A.expressionInExtendedField(block: FunctionalExpressionExtendedField.() -> Expression): Expression = - FunctionalExpressionExtendedField(this).block() +public inline fun > A.expressionInExtendedField( + block: FunctionalExpressionExtendedField.() -> Expression, +): Expression = FunctionalExpressionExtendedField(this).block() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt index c710ba679..4b5b3311e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -47,36 +47,6 @@ public fun DerivationResult.grad(vararg variables: Symbol): Point> F.simpleAutoDiff( - bindings: Map, - body: SimpleAutoDiffField.() -> AutoDiffValue, -): DerivationResult { - contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) } - - return SimpleAutoDiffField(this, bindings).differentiate(body) -} - -public fun > F.simpleAutoDiff( - vararg bindings: Pair, - body: SimpleAutoDiffField.() -> AutoDiffValue, -): DerivationResult = simpleAutoDiff(bindings.toMap(), body) - /** * Represents field in context of which functions can be derived. */ @@ -84,12 +54,9 @@ public fun > F.simpleAutoDiff( public open class SimpleAutoDiffField>( public val context: F, bindings: Map, -) : Field>, ExpressionAlgebra>, RingWithNumbers> { - public override val zero: AutoDiffValue - get() = const(context.zero) - - public override val one: AutoDiffValue - get() = const(context.one) +) : Field>, ExpressionAlgebra>, NumbersAddOperations> { + public override val zero: AutoDiffValue get() = const(context.zero) + public override val one: AutoDiffValue get() = const(context.one) // this stack contains pairs of blocks and values to apply them to private var stack: Array = arrayOfNulls(8) @@ -137,6 +104,8 @@ public open class SimpleAutoDiffField>( override fun const(value: T): AutoDiffValue = AutoDiffValue(value) + override fun number(value: Number): AutoDiffValue = const { one * value } + /** * A variable accessing inner state of derivatives. * Use this value in inner builders to avoid creating additional derivative bindings. @@ -175,21 +144,24 @@ public open class SimpleAutoDiffField>( return DerivationResult(result.value, bindings.mapValues { it.value.d }, context) } - // Overloads for Double constants +// // Overloads for Double constants +// +// public override operator fun Number.plus(b: AutoDiffValue): AutoDiffValue = +// derive(const { this@plus.toDouble() * one + b.value }) { z -> +// b.d += z.d +// } +// +// public override operator fun AutoDiffValue.plus(b: Number): AutoDiffValue = b.plus(this) +// +// public override operator fun Number.minus(b: AutoDiffValue): AutoDiffValue = +// derive(const { this@minus.toDouble() * one - b.value }) { z -> b.d -= z.d } +// +// public override operator fun AutoDiffValue.minus(b: Number): AutoDiffValue = +// derive(const { this@minus.value - one * b.toDouble() }) { z -> d += z.d } - public override operator fun Number.plus(b: AutoDiffValue): AutoDiffValue = - derive(const { this@plus.toDouble() * one + b.value }) { z -> - b.d += z.d - } - - public override operator fun AutoDiffValue.plus(b: Number): AutoDiffValue = b.plus(this) - - public override operator fun Number.minus(b: AutoDiffValue): AutoDiffValue = - derive(const { this@minus.toDouble() * one - b.value }) { z -> b.d -= z.d } - - public override operator fun AutoDiffValue.minus(b: Number): AutoDiffValue = - derive(const { this@minus.value - one * b.toDouble() }) { z -> this@minus.d += z.d } + override fun AutoDiffValue.unaryMinus(): AutoDiffValue = + derive(const { -value }) { z -> d -= z.d } // Basic math (+, -, *, /) @@ -211,12 +183,44 @@ public open class SimpleAutoDiffField>( b.d -= z.d * a.value / (b.value * b.value) } - public override fun multiply(a: AutoDiffValue, k: Number): AutoDiffValue = - derive(const { k.toDouble() * a.value }) { z -> - a.d += z.d * k.toDouble() + public override fun scale(a: AutoDiffValue, value: Double): AutoDiffValue = + derive(const { value * a.value }) { z -> + a.d += z.d * value } } + +/** + * Runs differentiation and establishes [SimpleAutoDiffField] context inside the block of code. + * + * The partial derivatives are placed in argument `d` variable + * + * Example: + * ``` + * val x by symbol // define variable(s) and their values + * val y = RealField.withAutoDiff() { sqr(x) + 5 * x + 3 } // write formulate in deriv context + * assertEquals(17.0, y.x) // the value of result (y) + * assertEquals(9.0, x.d) // dy/dx + * ``` + * + * @param body the action in [SimpleAutoDiffField] context returning [AutoDiffVariable] to differentiate with respect to. + * @return the result of differentiation. + */ +public fun > F.simpleAutoDiff( + bindings: Map, + body: SimpleAutoDiffField.() -> AutoDiffValue, +): DerivationResult { + contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) } + + return SimpleAutoDiffField(this, bindings).differentiate(body) +} + +public fun > F.simpleAutoDiff( + vararg bindings: Pair, + body: SimpleAutoDiffField.() -> AutoDiffValue, +): DerivationResult = simpleAutoDiff(bindings.toMap(), body) + + /** * A constructs that creates a derivative structure with required order on-demand */ @@ -247,19 +251,20 @@ public fun > simpleAutoDiff(field: F): AutoDiffProcessor> SimpleAutoDiffField.sqr(x: AutoDiffValue): AutoDiffValue = - derive(const { x.value * x.value }) { z -> x.d += z.d * 2 * x.value } +public fun > SimpleAutoDiffField.sqr(x: AutoDiffValue): AutoDiffValue = + derive(const { x.value * x.value }) { z -> x.d += z.d * 2.0 * x.value } // x ^ 1/2 public fun > SimpleAutoDiffField.sqrt(x: AutoDiffValue): AutoDiffValue = - derive(const { sqrt(x.value) }) { z -> x.d += z.d * 0.5 / z.value } + derive(const { sqrt(x.value) }) { z -> x.d += z.d / 2.0 / z.value } // x ^ y (const) public fun > SimpleAutoDiffField.pow( x: AutoDiffValue, y: Double, -): AutoDiffValue = - derive(const { power(x.value, y) }) { z -> x.d += z.d * y * power(x.value, y - 1) } +): AutoDiffValue = derive(const { power(x.value, y) }) { z -> + x.d += z.d * y * power(x.value, y - 1) +} public fun > SimpleAutoDiffField.pow( x: AutoDiffValue, @@ -328,7 +333,13 @@ public fun > SimpleAutoDiffField.atanh(x: Au public class SimpleAutoDiffExtendedField>( context: F, bindings: Map, -) : ExtendedField>, SimpleAutoDiffField(context, bindings) { +) : ExtendedField>, ScaleOperations>, + SimpleAutoDiffField(context, bindings) { + + override fun number(value: Number): AutoDiffValue = const { number(value) } + + override fun scale(a: AutoDiffValue, value: Double): AutoDiffValue = a * number(value) + // x ^ 2 public fun sqr(x: AutoDiffValue): AutoDiffValue = (this as SimpleAutoDiffField).sqr(x) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt index f8f7f5a05..ef1d82795 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt @@ -78,12 +78,12 @@ public class BufferMatrixContext>( } } - override fun multiply(a: Matrix, k: Number): BufferMatrix { - val aBufferMatrix = a.toBufferMatrix() - return elementContext { - produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() } - } - } +// override fun multiply(a: Matrix, k: Number): BufferMatrix { +// val aBufferMatrix = a.toBufferMatrix() +// return elementContext { +// produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() } +// } +// } public companion object } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt index c999a170c..639d77e85 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt @@ -1,10 +1,7 @@ package space.kscience.kmath.linear import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.SpaceOperations -import space.kscience.kmath.operations.invoke -import space.kscience.kmath.operations.sum +import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.asSequence @@ -167,9 +164,9 @@ public interface GenericMatrixContext, out M : Matrix> : return produce(rowNum, colNum) { i, j -> elementContext { get(i, j) + b[i, j] } } } - - public override fun multiply(a: Matrix, k: Number): M = - produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] * k } } +// +// public override fun multiply(a: Matrix, k: Number): M = +// produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] * k } } public override operator fun Matrix.times(value: T): M = produce(rowNum, colNum) { i, j -> elementContext { get(i, j) * value } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt index 5f28e6f4c..a53f0837f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt @@ -21,6 +21,8 @@ public object RealMatrixContext : MatrixContext> { if (i == j) 1.0 else 0.0 } + DiagonalFeature + override fun Matrix.unaryMinus(): Matrix = produce(rowNum, colNum) { i, j -> -get(i, j) } + public override infix fun Matrix.dot(other: Matrix): BufferMatrix { require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } val bufferMatrix = toBufferMatrix() @@ -60,12 +62,16 @@ public object RealMatrixContext : MatrixContext> { val bufferMatrix = toBufferMatrix() return produce(rowNum, colNum) { i, j -> bufferMatrix[i, j] * value } } - - - override fun multiply(a: Matrix, k: Number): BufferMatrix { - val aBufferMatrix = a.toBufferMatrix() - return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() } - } +// +// override fun multiply(a: Matrix, k: Number): BufferMatrix { +// val aBufferMatrix = a.toBufferMatrix() +// return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() } +// } +// +// override fun divide(a: Matrix, k: Number): BufferMatrix { +// val aBufferMatrix = a.toBufferMatrix() +// return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] / k.toDouble() } +// } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt index 310c1350c..fd3144d24 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.linear import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer @@ -10,21 +11,18 @@ import space.kscience.kmath.structures.BufferFactory * A linear space for vectors. * Could be used on any point-like structure */ -public interface VectorSpace> : Space> { +public interface VectorSpace> : Space> { public val size: Int - public val space: S - override val zero: Point get() = produce { space.zero } + public val algebra: A + override val zero: Point get() = produce { algebra.zero } - public fun produce(initializer: S.(Int) -> T): Point + public fun produce(initializer: A.(Int) -> T): Point - /** - * Produce a space-element of this vector space for expressions - */ - //fun produceElement(initializer: (Int) -> T): Vector + override fun add(a: Point, b: Point): Point = produce { algebra { a[it] + b[it] } } - override fun add(a: Point, b: Point): Point = produce { space { a[it] + b[it] } } + public fun scale(a: Point, scale: T): Point = produce { algebra { a[it] * scale } } - override fun multiply(a: Point, k: Number): Point = produce { space { a[it] * k } } + override fun Point.unaryMinus(): Point = produce { -get(it) } //TODO add basis @@ -45,26 +43,25 @@ public interface VectorSpace> : Space> { /** * A structured vector space with custom buffer */ - public fun > buffered( + public fun > buffered( size: Int, - space: S, + space: A, bufferFactory: BufferFactory = Buffer.Companion::boxing, - ): BufferVectorSpace = BufferVectorSpace(size, space, bufferFactory) + ): BufferVectorSpace = BufferVectorSpace(size, space, bufferFactory) /** * Automatic buffered vector, unboxed if it is possible */ - public inline fun > auto(size: Int, space: S): VectorSpace = + public inline fun > auto(size: Int, space: A): VectorSpace = buffered(size, space, Buffer.Companion::auto) } } -public class BufferVectorSpace>( +public class BufferVectorSpace>( override val size: Int, - override val space: S, + override val algebra: A, public val bufferFactory: BufferFactory, -) : VectorSpace { - override fun produce(initializer: S.(Int) -> T): Buffer = bufferFactory(size) { space.initializer(it) } - //override fun produceElement(initializer: (Int) -> T): Vector = BufferVector(this, produce(initializer)) +) : VectorSpace { + override fun produce(initializer: A.(Int) -> T): Buffer = bufferFactory(size) { algebra.initializer(it) } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt index 71c7d444c..ff9c911ac 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt @@ -1,19 +1,16 @@ package space.kscience.kmath.nd -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.RealField -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.Space +import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory import kotlin.contracts.InvocationKind import kotlin.contracts.contract -public interface BufferNDAlgebra : NDAlgebra { +public interface BufferNDAlgebra> : NDAlgebra { public val strides: Strides public val bufferFactory: BufferFactory - override fun produce(initializer: C.(IntArray) -> T): NDBuffer = NDBuffer( + override fun produce(initializer: A.(IntArray) -> T): NDBuffer = NDBuffer( strides, bufferFactory(strides.linearSize) { offset -> elementContext.initializer(strides.index(offset)) @@ -30,14 +27,14 @@ public interface BufferNDAlgebra : NDAlgebra { else -> bufferFactory(strides.linearSize) { offset -> get(strides.index(offset)) } } - override fun NDStructure.map(transform: C.(T) -> T): NDBuffer { + override fun NDStructure.map(transform: A.(T) -> T): NDBuffer { val buffer = bufferFactory(strides.linearSize) { offset -> elementContext.transform(buffer[offset]) } return NDBuffer(strides, buffer) } - override fun NDStructure.mapIndexed(transform: C.(index: IntArray, T) -> T): NDBuffer { + override fun NDStructure.mapIndexed(transform: A.(index: IntArray, T) -> T): NDBuffer { val buffer = bufferFactory(strides.linearSize) { offset -> elementContext.transform( strides.index(offset), @@ -47,7 +44,7 @@ public interface BufferNDAlgebra : NDAlgebra { return NDBuffer(strides, buffer) } - override fun combine(a: NDStructure, b: NDStructure, transform: C.(T, T) -> T): NDBuffer { + override fun combine(a: NDStructure, b: NDStructure, transform: A.(T, T) -> T): NDBuffer { val buffer = bufferFactory(strides.linearSize) { offset -> elementContext.transform(a.buffer[offset], b.buffer[offset]) } @@ -55,13 +52,14 @@ public interface BufferNDAlgebra : NDAlgebra { } } -public open class BufferedNDSpace>( +public open class BufferedNDSpace>( final override val shape: IntArray, - final override val elementContext: R, + final override val elementContext: A, final override val bufferFactory: BufferFactory, -) : NDSpace, BufferNDAlgebra { +) : NDSpace, BufferNDAlgebra { override val strides: Strides = DefaultStrides(shape) override val zero: NDBuffer by lazy { produce { zero } } + override fun NDStructure.unaryMinus(): NDStructure = produce { -get(it) } } public open class BufferedNDRing>( @@ -76,7 +74,10 @@ public open class BufferedNDField>( shape: IntArray, elementContext: R, bufferFactory: BufferFactory, -) : BufferedNDRing(shape, elementContext, bufferFactory), NDField +) : BufferedNDRing(shape, elementContext, bufferFactory), NDField { + + override fun scale(a: NDStructure, value: Double): NDStructure = a.map { it * value } +} // space factories public fun > NDAlgebra.Companion.space( diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt index af154d3cd..6b6e887dc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt @@ -1,8 +1,6 @@ package space.kscience.kmath.nd -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.Space +import space.kscience.kmath.operations.* import space.kscience.kmath.structures.* /** @@ -21,7 +19,7 @@ public class ShapeMismatchException(public val expected: IntArray, public val ac * @param C the type of the element context. * @param N the type of the structure. */ -public interface NDAlgebra { +public interface NDAlgebra> { /** * The shape of ND-structures this algebra operates on. */ @@ -33,7 +31,7 @@ public interface NDAlgebra { public val elementContext: C /** - * Produces a new [N] structure using given initializer function. + * Produces a new NDStructure using given initializer function. */ public fun produce(initializer: C.(IntArray) -> T): NDStructure @@ -67,7 +65,7 @@ public interface NDAlgebra { * @param structures the structures to check. * @return the array of valid structures. */ -internal fun NDAlgebra.checkShape(vararg structures: NDStructure): Array> = structures +internal fun > NDAlgebra.checkShape(vararg structures: NDStructure): Array> = structures .map(NDStructure::shape) .singleOrNull { !shape.contentEquals(it) } ?.let>> { throw ShapeMismatchException(shape, it) } @@ -79,7 +77,7 @@ internal fun NDAlgebra.checkShape(vararg structures: NDStructure * @param element the structure to check. * @return the valid structure. */ -internal fun NDAlgebra.checkShape(element: NDStructure): NDStructure { +internal fun > NDAlgebra.checkShape(element: NDStructure): NDStructure { if (!element.shape.contentEquals(shape)) throw ShapeMismatchException(shape, element.shape) return element } @@ -102,14 +100,14 @@ public interface NDSpace> : Space>, NDAlgebra, b: NDStructure): NDStructure = combine(a, b) { aValue, bValue -> add(aValue, bValue) } - /** - * Element-wise multiplication by scalar. - * - * @param a the multiplicand. - * @param k the multiplier. - * @return the product. - */ - public override fun multiply(a: NDStructure, k: Number): NDStructure = a.map() { multiply(it, k) } +// /** +// * Element-wise multiplication by scalar. +// * +// * @param a the multiplicand. +// * @param k the multiplier. +// * @return the product. +// */ +// public override fun multiply(a: NDStructure, k: Number): NDStructure = a.map { multiply(it, k) } // TODO move to extensions after KEEP-176 @@ -120,7 +118,7 @@ public interface NDSpace> : Space>, NDAlgebra.plus(arg: T): NDStructure = this.map() { value -> add(arg, value) } + public operator fun NDStructure.plus(arg: T): NDStructure = this.map { value -> add(arg, value) } /** * Subtracts an element from ND structure of it. @@ -200,7 +198,7 @@ public interface NDRing> : Ring>, NDSpace { * @param N the type of ND structure. * @param F the type field of structure elements. */ -public interface NDField> : Field>, NDRing { +public interface NDField> : Field>, NDRing, ScaleOperations> { /** * Element-wise division. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt index 73ba337ae..2165aea22 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt @@ -2,8 +2,9 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.operations.NumbersAddOperations import space.kscience.kmath.operations.RealField -import space.kscience.kmath.operations.RingWithNumbers +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.RealBuffer import kotlin.contracts.InvocationKind @@ -13,7 +14,8 @@ import kotlin.contracts.contract public class RealNDField( shape: IntArray, ) : BufferedNDField(shape, RealField, Buffer.Companion::real), - RingWithNumbers>, + NumbersAddOperations>, + ScaleOperations>, ExtendedField> { override val zero: NDBuffer by lazy { produce { zero } } @@ -75,6 +77,8 @@ public class RealNDField( return NDBuffer(strides, buffer) } + override fun scale(a: NDStructure, value: Double): NDStructure = a.map { it * value } + override fun power(arg: NDStructure, pow: Number): NDBuffer = arg.map { power(it, pow) } override fun exp(arg: NDStructure): NDBuffer = arg.map { exp(it) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt index 30960a090..2085840a4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.RingWithNumbers +import space.kscience.kmath.operations.NumbersAddOperations import space.kscience.kmath.operations.ShortRing import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.ShortBuffer @@ -12,7 +12,7 @@ import kotlin.contracts.contract public class ShortNDRing( shape: IntArray, ) : BufferedNDRing(shape, ShortRing, Buffer.Companion::auto), - RingWithNumbers> { + NumbersAddOperations> { override val zero: NDBuffer by lazy { produce { zero } } override val one: NDBuffer by lazy { produce { one } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 572f7089a..2163f61b2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -87,10 +87,11 @@ public interface Algebra { * @param right the second argument of operation. * @return a result of operation. */ - public fun binaryOperation(operation: String, left: T, right: T): T = binaryOperationFunction(operation)(left, right) + public fun binaryOperation(operation: String, left: T, right: T): T = + binaryOperationFunction(operation)(left, right) } -public fun Algebra.bindSymbol(symbol: Symbol): T = bindSymbol(symbol.identity) +public fun Algebra.bindSymbol(symbol: Symbol): T = bindSymbol(symbol.identity) /** * Call a block with an [Algebra] as receiver. @@ -114,15 +115,6 @@ public interface SpaceOperations : Algebra { */ public fun add(a: T, b: T): T - /** - * Multiplication of element by scalar. - * - * @param a the multiplier. - * @param k the multiplicand. - * @return the produce. - */ - public fun multiply(a: T, k: Number): T - // Operations to be performed in this context. Could be moved to extensions in case of KEEP-176 /** @@ -131,7 +123,7 @@ public interface SpaceOperations : Algebra { * @receiver this value. * @return the additive inverse of this value. */ - public operator fun T.unaryMinus(): T = multiply(this, -1.0) + public operator fun T.unaryMinus(): T /** * Returns this value. @@ -159,34 +151,6 @@ public interface SpaceOperations : Algebra { */ public operator fun T.minus(b: T): T = add(this, -b) - /** - * Multiplication of this element by a scalar. - * - * @receiver the multiplier. - * @param k the multiplicand. - * @return the product. - */ - public operator fun T.times(k: Number): T = multiply(this, k) - - /** - * Division of this element by scalar. - * - * @receiver the dividend. - * @param k the divisor. - * @return the quotient. - */ - @Deprecated("Dividing not allowed in a Ring") - public operator fun T.div(k: Number): T = multiply(this, 1.0 / k.toDouble()) - - /** - * Multiplication of this number by element. - * - * @receiver the multiplier. - * @param b the multiplicand. - * @return the product. - */ - public operator fun Number.times(b: T): T = b * this - public override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) { PLUS_OPERATION -> { arg -> arg } MINUS_OPERATION -> { arg -> -arg } @@ -318,13 +282,6 @@ public interface FieldOperations : RingOperations { * * @param T the type of element of this semifield. */ -public interface Field : Ring, FieldOperations { - /** - * Division of element by scalar. - * - * @receiver the dividend. - * @param b the divisor. - * @return the quotient. - */ - public operator fun Number.div(b: T): T = this * divide(one, b) -} +public interface Field : Ring, FieldOperations, ScaleOperations, NumericAlgebra { + override fun number(value: Number): T = scale(one, value.toDouble()) +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt index 629c4de1b..1fb4f6750 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt @@ -14,24 +14,24 @@ public interface AlgebraElement> { */ public val context: C } - -/** - * Divides this element by number. - * - * @param k the divisor. - * @return the quotient. - */ -public operator fun , S : Space> T.div(k: Number): T = - context.multiply(this, 1.0 / k.toDouble()) - -/** - * Multiplies this element by number. - * - * @param k the multiplicand. - * @return the product. - */ -public operator fun , S : Space> T.times(k: Number): T = - context.multiply(this, k.toDouble()) +// +///** +// * Divides this element by number. +// * +// * @param k the divisor. +// * @return the quotient. +// */ +//public operator fun , S : Space> T.div(k: Number): T = +// context.multiply(this, 1.0 / k.toDouble()) +// +///** +// * Multiplies this element by number. +// * +// * @param k the multiplicand. +// * @return the product. +// */ +//public operator fun , S : Space> T.times(k: Number): T = +// context.multiply(this, k.toDouble()) /** * Subtracts element from this one. @@ -39,8 +39,9 @@ public operator fun , S : Space> T.times(k: Number): * @param b the subtrahend. * @return the difference. */ -public operator fun , S : Space> T.minus(b: T): T = - context.add(this, context.multiply(b, -1.0)) +@UnstableKMathAPI +public operator fun , S : NumbersAddOperations> T.minus(b: T): T = + context.add(this, context.run { -b}) /** * Adds element to this one. @@ -51,11 +52,11 @@ public operator fun , S : Space> T.minus(b: T): T = public operator fun , S : Space> T.plus(b: T): T = context.add(this, b) -/** - * Number times element - */ -public operator fun , S : Space> Number.times(element: T): T = - element.times(this) +///** +// * Number times element +// */ +//public operator fun , S : Space> Number.times(element: T): T = +// element.times(this) /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index c21260b82..7e6a2eb81 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -21,29 +21,28 @@ public typealias TBase = ULong * @author Robert Drynkin (https://github.com/robdrynkin) and Peter Klimai (https://github.com/pklimai) */ @OptIn(UnstableKMathAPI::class) -public object BigIntField : Field, RingWithNumbers { +public object BigIntField : Field, NumbersAddOperations, ScaleOperations { override val zero: BigInt = BigInt.ZERO override val one: BigInt = BigInt.ONE - override fun add(a: BigInt, b: BigInt): BigInt = a.plus(b) override fun number(value: Number): BigInt = value.toLong().toBigInt() - override fun multiply(a: BigInt, k: Number): BigInt = a.times(number(k)) - + @Suppress("EXTENSION_SHADOWED_BY_MEMBER") + override fun BigInt.unaryMinus(): BigInt = -this + override fun add(a: BigInt, b: BigInt): BigInt = a.plus(b) + override fun scale(a: BigInt, value: Double): BigInt = a.times(number(value)) override fun multiply(a: BigInt, b: BigInt): BigInt = a.times(b) + override fun divide(a: BigInt, b: BigInt): BigInt = a.div(b) public operator fun String.unaryPlus(): BigInt = this.parseBigInteger() ?: error("Can't parse $this as big integer") - public operator fun String.unaryMinus(): BigInt = -(this.parseBigInteger() ?: error("Can't parse $this as big integer")) - - override fun divide(a: BigInt, b: BigInt): BigInt = a.div(b) } public class BigInt internal constructor( private val sign: Byte, - private val magnitude: Magnitude - ) : Comparable { + private val magnitude: Magnitude, +) : Comparable { public override fun compareTo(other: BigInt): Int = when { (sign == 0.toByte()) and (other.sign == 0.toByte()) -> 0 sign < other.sign -> -1 diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt index 81f4c1fdf..187261b1d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt @@ -81,14 +81,53 @@ public interface NumericAlgebra : Algebra { rightSideNumberOperationFunction(operation)(left, right) } +/** + * Scale by scalar operations + */ +public interface ScaleOperations : Algebra { + /** + * Scaling of element by scalar. + * + * @param a the multiplier. + * @param value the multiplicand. + * @return the produce. + */ + public fun scale(a: T, value: Double): T + + /** + * Multiplication of this element by a scalar. + * + * @receiver the multiplier. + * @param k the multiplicand. + * @return the product. + */ + public operator fun T.times(k: Number): T = scale(this, k.toDouble()) + + /** + * Division of this element by scalar. + * + * @receiver the dividend. + * @param k the divisor. + * @return the quotient. + */ + public operator fun T.div(k: Number): T = scale(this, 1.0 / k.toDouble()) + + /** + * Multiplication of this number by element. + * + * @receiver the multiplier. + * @param b the multiplicand. + * @return the product. + */ + public operator fun Number.times(b: T): T = b * this +} + /** * A combination of [NumericAlgebra] and [Ring] that adds intrinsic simple operations on numbers like `T+1` * TODO to be removed and replaced by extensions after multiple receivers are there */ @UnstableKMathAPI -public interface RingWithNumbers: Ring, NumericAlgebra{ - public override fun number(value: Number): T = one * value - +public interface NumbersAddOperations : Space, NumericAlgebra { /** * Addition of element and scalar. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt index 6cb329695..6e6249dfe 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt @@ -107,111 +107,6 @@ public fun >> acos(arg: T): @UnstableKMathAPI public fun >> atan(arg: T): T = arg.context.atan(arg) -/** - * A container for hyperbolic trigonometric operations for specific type. - * - * @param T the type of element of this structure. - */ -public interface HyperbolicOperations : Algebra { - /** - * Computes the hyperbolic sine of [arg]. - */ - public fun sinh(arg: T): T - - /** - * Computes the hyperbolic cosine of [arg]. - */ - public fun cosh(arg: T): T - - /** - * Computes the hyperbolic tangent of [arg]. - */ - public fun tanh(arg: T): T - - /** - * Computes the inverse hyperbolic sine of [arg]. - */ - public fun asinh(arg: T): T - - /** - * Computes the inverse hyperbolic cosine of [arg]. - */ - public fun acosh(arg: T): T - - /** - * Computes the inverse hyperbolic tangent of [arg]. - */ - public fun atanh(arg: T): T - - public companion object { - /** - * The identifier of hyperbolic sine. - */ - public const val SINH_OPERATION: String = "sinh" - - /** - * The identifier of hyperbolic cosine. - */ - public const val COSH_OPERATION: String = "cosh" - - /** - * The identifier of hyperbolic tangent. - */ - public const val TANH_OPERATION: String = "tanh" - - /** - * The identifier of inverse hyperbolic sine. - */ - public const val ASINH_OPERATION: String = "asinh" - - /** - * The identifier of inverse hyperbolic cosine. - */ - public const val ACOSH_OPERATION: String = "acosh" - - /** - * The identifier of inverse hyperbolic tangent. - */ - public const val ATANH_OPERATION: String = "atanh" - } -} - -/** - * Computes the hyperbolic sine of [arg]. - */ -@UnstableKMathAPI -public fun >> sinh(arg: T): T = arg.context.sinh(arg) - -/** - * Computes the hyperbolic cosine of [arg]. - */ -@UnstableKMathAPI -public fun >> cosh(arg: T): T = arg.context.cosh(arg) - -/** - * Computes the hyperbolic tangent of [arg]. - */ -@UnstableKMathAPI -public fun >> tanh(arg: T): T = arg.context.tanh(arg) - -/** - * Computes the inverse hyperbolic sine of [arg]. - */ -@UnstableKMathAPI -public fun >> asinh(arg: T): T = arg.context.asinh(arg) - -/** - * Computes the inverse hyperbolic cosine of [arg]. - */ -@UnstableKMathAPI -public fun >> acosh(arg: T): T = arg.context.acosh(arg) - -/** - * Computes the inverse hyperbolic tangent of [arg]. - */ -@UnstableKMathAPI -public fun >> atanh(arg: T): T = arg.context.atanh(arg) - /** * A context extension to include power operations based on exponentiation. * @@ -284,6 +179,36 @@ public interface ExponentialOperations : Algebra { */ public fun ln(arg: T): T + /** + * Computes the hyperbolic sine of [arg]. + */ + public fun sinh(arg: T): T + + /** + * Computes the hyperbolic cosine of [arg]. + */ + public fun cosh(arg: T): T + + /** + * Computes the hyperbolic tangent of [arg]. + */ + public fun tanh(arg: T): T + + /** + * Computes the inverse hyperbolic sine of [arg]. + */ + public fun asinh(arg: T): T + + /** + * Computes the inverse hyperbolic cosine of [arg]. + */ + public fun acosh(arg: T): T + + /** + * Computes the inverse hyperbolic tangent of [arg]. + */ + public fun atanh(arg: T): T + public companion object { /** * The identifier of exponential function. @@ -294,6 +219,36 @@ public interface ExponentialOperations : Algebra { * The identifier of natural logarithm. */ public const val LN_OPERATION: String = "ln" + + /** + * The identifier of hyperbolic sine. + */ + public const val SINH_OPERATION: String = "sinh" + + /** + * The identifier of hyperbolic cosine. + */ + public const val COSH_OPERATION: String = "cosh" + + /** + * The identifier of hyperbolic tangent. + */ + public const val TANH_OPERATION: String = "tanh" + + /** + * The identifier of inverse hyperbolic sine. + */ + public const val ASINH_OPERATION: String = "asinh" + + /** + * The identifier of inverse hyperbolic cosine. + */ + public const val ACOSH_OPERATION: String = "acosh" + + /** + * The identifier of inverse hyperbolic tangent. + */ + public const val ATANH_OPERATION: String = "atanh" } } @@ -309,6 +264,43 @@ public fun >> exp(arg: T): T @UnstableKMathAPI public fun >> ln(arg: T): T = arg.context.ln(arg) + +/** + * Computes the hyperbolic sine of [arg]. + */ +@UnstableKMathAPI +public fun >> sinh(arg: T): T = arg.context.sinh(arg) + +/** + * Computes the hyperbolic cosine of [arg]. + */ +@UnstableKMathAPI +public fun >> cosh(arg: T): T = arg.context.cosh(arg) + +/** + * Computes the hyperbolic tangent of [arg]. + */ +@UnstableKMathAPI +public fun >> tanh(arg: T): T = arg.context.tanh(arg) + +/** + * Computes the inverse hyperbolic sine of [arg]. + */ +@UnstableKMathAPI +public fun >> asinh(arg: T): T = arg.context.asinh(arg) + +/** + * Computes the inverse hyperbolic cosine of [arg]. + */ +@UnstableKMathAPI +public fun >> acosh(arg: T): T = arg.context.acosh(arg) + +/** + * Computes the inverse hyperbolic tangent of [arg]. + */ +@UnstableKMathAPI +public fun >> atanh(arg: T): T = arg.context.atanh(arg) + /** * A container for norm functional on element. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index ae1267d2b..66b16b6f6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -26,7 +26,8 @@ public fun Space.sum(data: Sequence): T = data.fold(zero) { left, righ * @return the average value. * @author Iaroslav Postovalov */ -public fun Space.average(data: Iterable): T = sum(data) / data.count() +public fun S.average(data: Iterable): T where S : Space, S : ScaleOperations = + sum(data) / data.count() /** * Returns an average value of elements in the sequence in this [Space]. @@ -36,7 +37,8 @@ public fun Space.average(data: Iterable): T = sum(data) / data.count() * @return the average value. * @author Iaroslav Postovalov */ -public fun Space.average(data: Sequence): T = sum(data) / data.count() +public fun S.average(data: Sequence): T where S : Space, S : ScaleOperations = + sum(data) / data.count() /** * Absolute of the comparable [value] @@ -69,7 +71,8 @@ public fun Sequence.sumWith(space: Space): T = space.sum(this) * @return the average value. * @author Iaroslav Postovalov */ -public fun Iterable.averageWith(space: Space): T = space.average(this) +public fun Iterable.averageWith(space: S): T where S : Space, S : ScaleOperations = + space.average(this) /** * Returns an average value of elements in the sequence in this [Space]. @@ -79,7 +82,8 @@ public fun Iterable.averageWith(space: Space): T = space.average(this) * @return the average value. * @author Iaroslav Postovalov */ -public fun Sequence.averageWith(space: Space): T = space.average(this) +public fun Sequence.averageWith(space: S): T where S : Space, S : ScaleOperations = + space.average(this) //TODO optimized power operation diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt index aa62715d1..4841e78d6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt @@ -8,7 +8,6 @@ import kotlin.math.pow as kpow public interface ExtendedFieldOperations : FieldOperations, TrigonometricOperations, - HyperbolicOperations, PowerOperations, ExponentialOperations { public override fun tan(arg: T): T = sin(arg) / cos(arg) @@ -21,15 +20,15 @@ public interface ExtendedFieldOperations : TrigonometricOperations.ACOS_OPERATION -> ::acos TrigonometricOperations.ASIN_OPERATION -> ::asin TrigonometricOperations.ATAN_OPERATION -> ::atan - HyperbolicOperations.COSH_OPERATION -> ::cosh - HyperbolicOperations.SINH_OPERATION -> ::sinh - HyperbolicOperations.TANH_OPERATION -> ::tanh - HyperbolicOperations.ACOSH_OPERATION -> ::acosh - HyperbolicOperations.ASINH_OPERATION -> ::asinh - HyperbolicOperations.ATANH_OPERATION -> ::atanh PowerOperations.SQRT_OPERATION -> ::sqrt ExponentialOperations.EXP_OPERATION -> ::exp ExponentialOperations.LN_OPERATION -> ::ln + ExponentialOperations.COSH_OPERATION -> ::cosh + ExponentialOperations.SINH_OPERATION -> ::sinh + ExponentialOperations.TANH_OPERATION -> ::tanh + ExponentialOperations.ACOSH_OPERATION -> ::acosh + ExponentialOperations.ASINH_OPERATION -> ::asinh + ExponentialOperations.ATANH_OPERATION -> ::atanh else -> super.unaryOperationFunction(operation) } } @@ -37,18 +36,18 @@ public interface ExtendedFieldOperations : /** * Advanced Number-like field that implements basic operations. */ -public interface ExtendedField : ExtendedFieldOperations, Field, NumericAlgebra { - public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2 - public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2 +public interface ExtendedField : ExtendedFieldOperations, Field, NumericAlgebra, ScaleOperations { + public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2.0 + public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2.0 public override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg)) public override fun asinh(arg: T): T = ln(sqrt(arg * arg + one) + arg) public override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one))) - public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2 + public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2.0 public override fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T = when (operation) { PowerOperations.POW_OPERATION -> ::power - else -> super.rightSideNumberOperationFunction(operation) + else -> super.rightSideNumberOperationFunction(operation) } } @@ -56,28 +55,27 @@ public interface ExtendedField : ExtendedFieldOperations, Field, Numeri * A field for [Double] without boxing. Does not produce appropriate field element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public object RealField : ExtendedField, Norm { - public override val zero: Double - get() = 0.0 - - public override val one: Double - get() = 1.0 +public object RealField : ExtendedField, Norm, ScaleOperations { + public override val zero: Double = 0.0 + public override val one: Double = 1.0 override fun number(value: Number): Double = value.toDouble() public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double = when (operation) { PowerOperations.POW_OPERATION -> ::power - else -> super.binaryOperationFunction(operation) + else -> super.binaryOperationFunction(operation) } public override inline fun add(a: Double, b: Double): Double = a + b - public override inline fun multiply(a: Double, k: Number): Double = a * k.toDouble() +// public override inline fun multiply(a: Double, k: Number): Double = a * k.toDouble() +// override fun divide(a: Double, k: Number): Double = a / k.toDouble() public override inline fun multiply(a: Double, b: Double): Double = a * b - public override inline fun divide(a: Double, b: Double): Double = a / b + override fun scale(a: Double, value: Double): Double = a * value + public override inline fun sin(arg: Double): Double = kotlin.math.sin(arg) public override inline fun cos(arg: Double): Double = kotlin.math.cos(arg) public override inline fun tan(arg: Double): Double = kotlin.math.tan(arg) @@ -110,11 +108,8 @@ public object RealField : ExtendedField, Norm { */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object FloatField : ExtendedField, Norm { - public override val zero: Float - get() = 0.0f - - public override val one: Float - get() = 1.0f + public override val zero: Float = 0.0f + public override val one: Float = 1.0f override fun number(value: Number): Float = value.toFloat() @@ -125,7 +120,7 @@ public object FloatField : ExtendedField, Norm { } public override inline fun add(a: Float, b: Float): Float = a + b - public override inline fun multiply(a: Float, k: Number): Float = a * k.toFloat() + override fun scale(a: Float, value: Double): Float = a * value.toFloat() public override inline fun multiply(a: Float, b: Float): Float = a * b @@ -170,12 +165,8 @@ public object IntRing : Ring, Norm, NumericAlgebra { get() = 1 override fun number(value: Number): Int = value.toInt() - public override inline fun add(a: Int, b: Int): Int = a + b - public override inline fun multiply(a: Int, k: Number): Int = k.toInt() * a - public override inline fun multiply(a: Int, b: Int): Int = a * b - public override inline fun norm(arg: Int): Int = abs(arg) public override inline fun Int.unaryMinus(): Int = -this @@ -196,12 +187,8 @@ public object ShortRing : Ring, Norm, NumericAlgebra get() = 1 override fun number(value: Number): Short = value.toShort() - public override inline fun add(a: Short, b: Short): Short = (a + b).toShort() - public override inline fun multiply(a: Short, k: Number): Short = (a * k.toShort()).toShort() - public override inline fun multiply(a: Short, b: Short): Short = (a * b).toShort() - public override fun norm(arg: Short): Short = if (arg > 0) arg else (-arg).toShort() public override inline fun Short.unaryMinus(): Short = (-this).toShort() @@ -222,12 +209,8 @@ public object ByteRing : Ring, Norm, NumericAlgebra { get() = 1 override fun number(value: Number): Byte = value.toByte() - public override inline fun add(a: Byte, b: Byte): Byte = (a + b).toByte() - public override inline fun multiply(a: Byte, k: Number): Byte = (a * k.toByte()).toByte() - public override inline fun multiply(a: Byte, b: Byte): Byte = (a * b).toByte() - public override fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte() public override inline fun Byte.unaryMinus(): Byte = (-this).toByte() @@ -248,12 +231,8 @@ public object LongRing : Ring, Norm, NumericAlgebra { get() = 1L override fun number(value: Number): Long = value.toLong() - public override inline fun add(a: Long, b: Long): Long = a + b - public override inline fun multiply(a: Long, k: Number): Long = a * k.toLong() - public override inline fun multiply(a: Long, b: Long): Long = a * b - public override fun norm(arg: Long): Long = abs(arg) public override inline fun Long.unaryMinus(): Long = (-this) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt index 7351881ee..2a03a36e3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt @@ -8,6 +8,12 @@ import kotlin.math.* * [ExtendedFieldOperations] over [RealBuffer]. */ public object RealBufferFieldOperations : ExtendedFieldOperations> { + override fun Buffer.unaryMinus(): RealBuffer = if (this is RealBuffer) { + RealBuffer(size) { -array[it] } + } else { + RealBuffer(size) { -get(it) } + } + public override fun add(a: Buffer, b: Buffer): RealBuffer { require(b.size == a.size) { "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " @@ -19,15 +25,24 @@ public object RealBufferFieldOperations : ExtendedFieldOperations RealBuffer(DoubleArray(a.size) { aArray[it] + bArray[it] }) } else RealBuffer(DoubleArray(a.size) { a[it] + b[it] }) } - - public override fun multiply(a: Buffer, k: Number): RealBuffer { - val kValue = k.toDouble() - - return if (a is RealBuffer) { - val aArray = a.array - RealBuffer(DoubleArray(a.size) { aArray[it] * kValue }) - } else RealBuffer(DoubleArray(a.size) { a[it] * kValue }) - } +// +// public override fun multiply(a: Buffer, k: Number): RealBuffer { +// val kValue = k.toDouble() +// +// return if (a is RealBuffer) { +// val aArray = a.array +// RealBuffer(DoubleArray(a.size) { aArray[it] * kValue }) +// } else RealBuffer(DoubleArray(a.size) { a[it] * kValue }) +// } +// +// public override fun divide(a: Buffer, k: Number): RealBuffer { +// val kValue = k.toDouble() +// +// return if (a is RealBuffer) { +// val aArray = a.array +// RealBuffer(DoubleArray(a.size) { aArray[it] / kValue }) +// } else RealBuffer(DoubleArray(a.size) { a[it] / kValue }) +// } public override fun multiply(a: Buffer, b: Buffer): RealBuffer { require(b.size == a.size) { @@ -152,14 +167,22 @@ public class RealBufferField(public val size: Int) : ExtendedField = RealBuffer(size) { value.toDouble() } + override fun Buffer.unaryMinus(): Buffer = RealBufferFieldOperations.run { + -this@unaryMinus + } + public override fun add(a: Buffer, b: Buffer): RealBuffer { require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } return RealBufferFieldOperations.add(a, b) } - public override fun multiply(a: Buffer, k: Number): RealBuffer { + public override fun scale(a: Buffer, value: Double): RealBuffer { require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } - return RealBufferFieldOperations.multiply(a, k) + + return if (a is RealBuffer) { + val aArray = a.array + RealBuffer(DoubleArray(a.size) { aArray[it] * value }) + } else RealBuffer(DoubleArray(a.size) { a[it] * value }) } public override fun multiply(a: Buffer, b: Buffer): RealBuffer { diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt index c13850193..cf75eba3e 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt @@ -11,9 +11,7 @@ class ExpressionFieldTest { @Test fun testExpression() { - val context = FunctionalExpressionField(RealField) - - val expression = context { + val expression = FunctionalExpressionField(RealField).invoke { val x by binding() x * x + 2 * x + one } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt index 2aef6b27f..cdb0a7c5d 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt @@ -5,8 +5,9 @@ import space.kscience.kmath.operations.invoke import kotlin.test.assertEquals import kotlin.test.assertNotEquals -internal class FieldVerifier(override val algebra: Field, a: T, b: T, c: T, x: Number) : - RingVerifier(algebra, a, b, c, x) { +internal class FieldVerifier>( + algebra: A, a: T, b: T, c: T, x: Number, +) : RingVerifier(algebra, a, b, c, x) { override fun verify() { super.verify() diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt index dd8841806..6970c8ac7 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt @@ -1,11 +1,13 @@ package space.kscience.kmath.testutils import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import kotlin.test.assertEquals -internal open class RingVerifier(override val algebra: Ring, a: T, b: T, c: T, x: Number) : - SpaceVerifier(algebra, a, b, c, x) { +internal open class RingVerifier(algebra: A, a: T, b: T, c: T, x: Number) : + SpaceVerifier(algebra, a, b, c, x) where A : Ring, A : ScaleOperations { + override fun verify() { super.verify() diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt index f7a25b593..6ea75156b 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt @@ -1,18 +1,18 @@ package space.kscience.kmath.testutils +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.invoke import kotlin.test.assertEquals import kotlin.test.assertNotEquals -internal open class SpaceVerifier( - override val algebra: Space, +internal open class SpaceVerifier( + override val algebra: S, val a: T, val b: T, val c: T, - val x: Number -) : - AlgebraicVerifier> { + val x: Number, +) : AlgebraicVerifier> where S : Space, S : ScaleOperations { override fun verify() { algebra { assertEquals(a + b + c, a + (b + c), "Addition in $algebra is not associative.") diff --git a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt index 8f8b31ed9..0ac0ba1c5 100644 --- a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt +++ b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt @@ -7,19 +7,16 @@ import java.math.MathContext /** * A field over [BigInteger]. */ -public object JBigIntegerField : Field, NumericAlgebra { - public override val zero: BigInteger - get() = BigInteger.ZERO +public object JBigIntegerField : Ring, NumericAlgebra { + public override val zero: BigInteger get() = BigInteger.ZERO - public override val one: BigInteger - get() = BigInteger.ONE + public override val one: BigInteger get() = BigInteger.ONE public override fun number(value: Number): BigInteger = BigInteger.valueOf(value.toLong()) - public override fun divide(a: BigInteger, b: BigInteger): BigInteger = a.div(b) public override fun add(a: BigInteger, b: BigInteger): BigInteger = a.add(b) public override operator fun BigInteger.minus(b: BigInteger): BigInteger = subtract(b) - public override fun multiply(a: BigInteger, k: Number): BigInteger = a.multiply(k.toInt().toBigInteger()) public override fun multiply(a: BigInteger, b: BigInteger): BigInteger = a.multiply(b) + public override operator fun BigInteger.unaryMinus(): BigInteger = negate() } @@ -30,7 +27,7 @@ public object JBigIntegerField : Field, NumericAlgebra { */ public abstract class JBigDecimalFieldBase internal constructor( private val mathContext: MathContext = MathContext.DECIMAL64, -) : Field, PowerOperations, NumericAlgebra { +) : Field, PowerOperations, NumericAlgebra, ScaleOperations { public override val zero: BigDecimal get() = BigDecimal.ZERO @@ -41,8 +38,8 @@ public abstract class JBigDecimalFieldBase internal constructor( public override operator fun BigDecimal.minus(b: BigDecimal): BigDecimal = subtract(b) public override fun number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble()) - public override fun multiply(a: BigDecimal, k: Number): BigDecimal = - a.multiply(k.toDouble().toBigDecimal(mathContext), mathContext) + public override fun scale(a: BigDecimal, value: Double): BigDecimal = + a.multiply(value.toBigDecimal(mathContext), mathContext) public override fun multiply(a: BigDecimal, b: BigDecimal): BigDecimal = a.multiply(b, mathContext) public override fun divide(a: BigDecimal, b: BigDecimal): BigDecimal = a.divide(b, mathContext) diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt index 489cca8c1..eff813bee 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt @@ -5,16 +5,16 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.runningReduce import kotlinx.coroutines.flow.scan +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.SpaceOperations import space.kscience.kmath.operations.invoke -@ExperimentalCoroutinesApi public fun Flow.cumulativeSum(space: SpaceOperations): Flow = space { runningReduce { sum, element -> sum + element } } @ExperimentalCoroutinesApi -public fun Flow.mean(space: Space): Flow = space { +public fun Flow.mean(algebra: S): Flow where S : Space, S : ScaleOperations = algebra { data class Accumulator(var sum: T, var num: Int) scan(Accumulator(zero, 0)) { sum, element -> diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrixContext.kt index d67f80409..95c465975 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrixContext.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrixContext.kt @@ -4,13 +4,14 @@ import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.getFeature +import space.kscience.kmath.operations.ScaleOperations /** * Represents context of basic operations operating with [EjmlMatrix]. * * @author Iaroslav Postovalov */ -public object EjmlMatrixContext : MatrixContext { +public object EjmlMatrixContext : MatrixContext, ScaleOperations> { /** * Converts this matrix to EJML one. @@ -41,6 +42,9 @@ public object EjmlMatrixContext : MatrixContext { (0 until it.numRows()).forEach { row -> it[row, 0] = initializer(row) } }) + + override fun Matrix.unaryMinus(): Matrix = this*(-1) + public override fun Matrix.dot(other: Matrix): EjmlMatrix = EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) @@ -53,8 +57,8 @@ public object EjmlMatrixContext : MatrixContext { public override operator fun Matrix.minus(b: Matrix): EjmlMatrix = EjmlMatrix(toEjml().origin - b.toEjml().origin) - public override fun multiply(a: Matrix, k: Number): EjmlMatrix = - produce(a.rowNum, a.colNum) { i, j -> a[i, j] * k.toDouble() } + public override fun scale(a: Matrix, value: Double): EjmlMatrix = + produce(a.rowNum, a.colNum) { i, j -> a[i, j] * value } public override operator fun Matrix.times(value: Double): EjmlMatrix = EjmlMatrix(toEjml().origin.scale(value)) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index b1e47f34c..7416069bd 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.invoke import kotlin.contracts.InvocationKind @@ -41,9 +42,15 @@ public fun > Polynomial.asFunction(ring: C): (T) -> T = /** * An algebra for polynomials */ -public class PolynomialSpace>(private val ring: C) : Space> { +public class PolynomialSpace( + private val ring: C, +) : Space>, ScaleOperations> where C: Ring, C: ScaleOperations{ public override val zero: Polynomial = Polynomial(emptyList()) + override fun Polynomial.unaryMinus(): Polynomial = with(ring) { + Polynomial(coefficients.map { -it }) + } + public override fun add(a: Polynomial, b: Polynomial): Polynomial { val dim = max(a.coefficients.size, b.coefficients.size) @@ -54,13 +61,13 @@ public class PolynomialSpace>(private val ring: C) : Space< } } - public override fun multiply(a: Polynomial, k: Number): Polynomial = - ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * k }) } + public override fun scale(a: Polynomial, value: Double): Polynomial = + ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) } public operator fun Polynomial.invoke(arg: T): T = value(ring, arg) } -public inline fun , R> C.polynomial(block: PolynomialSpace.() -> R): R { +public inline fun C.polynomial(block: PolynomialSpace.() -> R): R where C: Ring, C: ScaleOperations{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return PolynomialSpace(this).block() } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index 34fd25ad4..78d6e0d0c 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -11,9 +11,9 @@ import space.kscience.kmath.structures.MutableBufferFactory * Generic spline interpolator. Not recommended for performance critical places, use platform-specific and type specific ones. * Based on https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/SplineInterpolator.java */ -public class SplineInterpolator>( - public override val algebra: Field, - public val bufferFactory: MutableBufferFactory +public class SplineInterpolator, F : Field>( + public override val algebra: F, + public val bufferFactory: MutableBufferFactory, ) : PolynomialInterpolator { //TODO possibly optimize zeroed buffers diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt index 609274d7d..54a1e032c 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt @@ -2,6 +2,7 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.SpaceElement import space.kscience.kmath.operations.invoke import kotlin.math.sqrt @@ -30,18 +31,20 @@ public fun Vector2D(x: Double, y: Double): Vector2D = Vector2DImpl(x, y) private data class Vector2DImpl( override val x: Double, - override val y: Double + override val y: Double, ) : Vector2D /** * 2D Euclidean space */ -public object Euclidean2DSpace : GeometrySpace { +public object Euclidean2DSpace : GeometrySpace, ScaleOperations { public override val zero: Vector2D by lazy { Vector2D(0.0, 0.0) } public fun Vector2D.norm(): Double = sqrt(x * x + y * y) + override fun Vector2D.unaryMinus(): Vector2D = Vector2D(-x, -y) + public override fun Vector2D.distanceTo(other: Vector2D): Double = (this - other).norm() public override fun add(a: Vector2D, b: Vector2D): Vector2D = Vector2D(a.x + b.x, a.y + b.y) - public override fun multiply(a: Vector2D, k: Number): Vector2D = Vector2D(a.x * k.toDouble(), a.y * k.toDouble()) + public override fun scale(a: Vector2D, value: Double): Vector2D = Vector2D(a.x * value, a.y * value) public override fun Vector2D.dot(other: Vector2D): Double = x * other.x + y * other.y } diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt index 906f5df03..ed110e383 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt @@ -2,6 +2,7 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.SpaceElement import space.kscience.kmath.operations.invoke import kotlin.math.sqrt @@ -32,21 +33,22 @@ public val Vector3D.r: Double get() = Euclidean3DSpace { sqrt(norm()) } private data class Vector3DImpl( override val x: Double, override val y: Double, - override val z: Double + override val z: Double, ) : Vector3D -public object Euclidean3DSpace : GeometrySpace { +public object Euclidean3DSpace : GeometrySpace, ScaleOperations { public override val zero: Vector3D by lazy { Vector3D(0.0, 0.0, 0.0) } public fun Vector3D.norm(): Double = sqrt(x * x + y * y + z * z) + override fun Vector3D.unaryMinus(): Vector3D = Vector3D(-x, -y, -z) public override fun Vector3D.distanceTo(other: Vector3D): Double = (this - other).norm() public override fun add(a: Vector3D, b: Vector3D): Vector3D = Vector3D(a.x + b.x, a.y + b.y, a.z + b.z) - public override fun multiply(a: Vector3D, k: Number): Vector3D = - Vector3D(a.x * k.toDouble(), a.y * k.toDouble(), a.z * k.toDouble()) + public override fun scale(a: Vector3D, value: Double): Vector3D = + Vector3D(a.x * value, a.y * value, a.z * value) public override fun Vector3D.dot(other: Vector3D): Double = x * other.x + y * other.y + z * other.z diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt index 85262abeb..b82644481 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt @@ -3,9 +3,10 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.Domain import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.NDSpace +import space.kscience.kmath.nd.NDField import space.kscience.kmath.nd.NDStructure import space.kscience.kmath.nd.Strides +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.SpaceElement import space.kscience.kmath.operations.invoke @@ -41,10 +42,11 @@ public class IndexedHistogram, V : Any>( /** * A space for producing histograms with values in a NDStructure */ -public interface IndexedHistogramSpace, V : Any> : Space> { +public interface IndexedHistogramSpace, V : Any> + : Space>, ScaleOperations> { //public val valueSpace: Space public val strides: Strides - public val histogramValueSpace: NDSpace //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape), + public val histogramValueSpace: NDField //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape), /** * Resolve index of the bin including given [point] @@ -63,12 +65,12 @@ public interface IndexedHistogramSpace, V : Any> : Space, b: IndexedHistogram): IndexedHistogram { require(a.context == this) { "Can't operate on a histogram produced by external space" } require(b.context == this) { "Can't operate on a histogram produced by external space" } - return IndexedHistogram(this, histogramValueSpace.invoke { a.values + b.values }) + return IndexedHistogram(this, histogramValueSpace { a.values + b.values }) } - override fun multiply(a: IndexedHistogram, k: Number): IndexedHistogram { + override fun scale(a: IndexedHistogram, value: Double): IndexedHistogram { require(a.context == this) { "Can't operate on a histogram produced by external space" } - return IndexedHistogram(this, histogramValueSpace.invoke { a.values * k }) + return IndexedHistogram(this, histogramValueSpace { a.values * value }) } override val zero: IndexedHistogram get() = produce { } diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt index 26efdf1fe..3df0b1626 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt @@ -2,6 +2,7 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.Domain import space.kscience.kmath.domains.HyperSquareDomain +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.structures.* import kotlin.math.floor @@ -40,6 +41,7 @@ public class RealHistogramSpace( getIndex(it, point[it]) } + @OptIn(UnstableKMathAPI::class) override fun getDomain(index: IntArray): Domain { val lowerBoundary = index.mapIndexed { axis, i -> when (i) { @@ -77,6 +79,8 @@ public class RealHistogramSpace( return IndexedHistogram(this, values) } + override fun IndexedHistogram.unaryMinus(): IndexedHistogram = this * (-1) + public companion object { /** * Use it like diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt index ddecc4332..85e82f515 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt @@ -2,6 +2,7 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.UnivariateDomain import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.Space import space.kscience.kmath.structures.Buffer import java.util.* @@ -36,7 +37,7 @@ public class TreeHistogram( @UnstableKMathAPI public class TreeHistogramSpace( public val binFactory: (Double) -> UnivariateDomain, -) : Space { +) : Space, ScaleOperations { private class BinCounter(val domain: UnivariateDomain, val counter: Counter = Counter.real()) : ClosedFloatingPointRange by domain.range @@ -97,14 +98,14 @@ public class TreeHistogramSpace( return TreeHistogram(this, bins) } - override fun multiply(a: UnivariateHistogram, k: Number): UnivariateHistogram { + override fun scale(a: UnivariateHistogram, value: Double): UnivariateHistogram { val bins = TreeMap().apply { a.bins.forEach { bin -> put(bin.domain.center, UnivariateBin( bin.domain, - value = bin.value * k.toDouble(), - standardDeviation = abs(bin.standardDeviation * k.toDouble()) + value = bin.value * value.toDouble(), + standardDeviation = abs(bin.standardDeviation * value.toDouble()) ) ) } @@ -113,6 +114,8 @@ public class TreeHistogramSpace( return TreeHistogram(this, bins) } + override fun UnivariateHistogram.unaryMinus(): UnivariateHistogram = this * (-1) + override val zero: UnivariateHistogram = produce { } public companion object { diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt index 8c4f9e434..96e3d41ae 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt @@ -8,6 +8,7 @@ import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asSequence +@UnstableKMathAPI public val UnivariateDomain.center: Double get() = (range.endInclusive - range.start) / 2 /** @@ -15,6 +16,7 @@ public val UnivariateDomain.center: Double get() = (range.endInclusive - range.s * @param value The value of histogram including weighting * @param standardDeviation Standard deviation of the bin value. Zero or negative if not applicable */ +@UnstableKMathAPI public class UnivariateBin( public val domain: UnivariateDomain, override val value: Double, diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index c50174b95..11e7b73e4 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -20,7 +20,7 @@ internal fun NDAlgebra<*, *>.checkShape(array: INDArray): INDArray { * @param T the type of ND-structure element. * @param C the type of the element context. */ -public interface Nd4jArrayAlgebra : NDAlgebra { +public interface Nd4jArrayAlgebra> : NDAlgebra { /** * Wraps [INDArray] to [N]. */ @@ -92,18 +92,9 @@ public interface Nd4jArraySpace> : NDSpace, Nd4jArrayAlgeb return ndArray.neg().wrap() } - public override fun multiply(a: NDStructure, k: Number): Nd4jArrayStructure { + public fun multiply(a: NDStructure, k: Number): Nd4jArrayStructure { return a.ndArray.mul(k).wrap() } - - @Deprecated("Avoid using this method, underlying array get casted to Doubles") - public override operator fun NDStructure.div(k: Number): Nd4jArrayStructure { - return ndArray.div(k).wrap() - } - - public override operator fun NDStructure.times(k: Number): Nd4jArrayStructure { - return ndArray.mul(k).wrap() - } } /** @@ -180,8 +171,7 @@ public interface Nd4jArrayField> : NDField, Nd4jArrayRing< public override fun divide(a: NDStructure, b: NDStructure): Nd4jArrayStructure = a.ndArray.div(b.ndArray).wrap() - public override operator fun Number.div(b: NDStructure): Nd4jArrayStructure = b.ndArray.rdiv(this).wrap() - + public operator fun Number.div(b: NDStructure): Nd4jArrayStructure = b.ndArray.rdiv(this).wrap() public companion object { private val floatNd4jArrayFieldCache: ThreadLocal> = @@ -218,11 +208,14 @@ public interface Nd4jArrayField> : NDField, Nd4jArrayRing< * Represents [NDField] over [Nd4jArrayRealStructure]. */ public class RealNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField { - public override val elementContext: RealField - get() = RealField + public override val elementContext: RealField get() = RealField public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asRealStructure() + override fun scale(a: NDStructure, value: Double): Nd4jArrayStructure { + return a.ndArray.mul(value).wrap() + } + public override operator fun NDStructure.div(arg: Double): Nd4jArrayStructure { return ndArray.div(arg).wrap() } @@ -257,6 +250,10 @@ public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArra public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asFloatStructure() + override fun scale(a: NDStructure, value: Double): NDStructure { + return a.ndArray.mul(value).wrap() + } + public override operator fun NDStructure.div(arg: Float): Nd4jArrayStructure { return ndArray.div(arg).wrap() } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt index 9fed91e1f..ca2fd58cc 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt @@ -4,6 +4,7 @@ import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.ConstantChain import space.kscience.kmath.chains.map import space.kscience.kmath.chains.zip +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.invoke @@ -18,14 +19,18 @@ public class ConstantSampler(public val value: T) : Sampler { /** * A space for samplers. Allows to perform simple operations on distributions */ -public class SamplerSpace(public val space: Space) : Space> { - public override val zero: Sampler = ConstantSampler(space.zero) +public class SamplerSpace(public val algebra: S) : Space>, + ScaleOperations> where S : Space, S : ScaleOperations { + + public override val zero: Sampler = ConstantSampler(algebra.zero) public override fun add(a: Sampler, b: Sampler): Sampler = BasicSampler { generator -> - a.sample(generator).zip(b.sample(generator)) { aValue, bValue -> space { aValue + bValue } } + a.sample(generator).zip(b.sample(generator)) { aValue, bValue -> algebra { aValue + bValue } } } - public override fun multiply(a: Sampler, k: Number): Sampler = BasicSampler { generator -> - a.sample(generator).map { space { it * k.toDouble() } } + public override fun scale(a: Sampler, value: Double): Sampler = BasicSampler { generator -> + a.sample(generator).map { algebra { it * value } } } + + override fun Sampler.unaryMinus(): Sampler = scale(this, -1.0) } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt index 29ded2b88..4a3103d1b 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt @@ -43,7 +43,7 @@ public interface ComposableStatistic : Statistic { @ExperimentalCoroutinesApi private fun ComposableStatistic.flowIntermediate( flow: Flow>, - dispatcher: CoroutineDispatcher = Dispatchers.Default + dispatcher: CoroutineDispatcher = Dispatchers.Default, ): Flow = flow .mapParallel(dispatcher) { computeIntermediate(it) } .runningReduce(::composeIntermediate) @@ -59,27 +59,31 @@ private fun ComposableStatistic.flowIntermediate( @ExperimentalCoroutinesApi public fun ComposableStatistic.flow( flow: Flow>, - dispatcher: CoroutineDispatcher = Dispatchers.Default + dispatcher: CoroutineDispatcher = Dispatchers.Default, ): Flow = flowIntermediate(flow, dispatcher).map(::toResult) /** * Arithmetic mean */ -public class Mean(public val space: Space) : ComposableStatistic, T> { +public class Mean( + private val space: Space, + private val division: (sum: T, count: Int) -> T, +) : ComposableStatistic, T> { public override suspend fun computeIntermediate(data: Buffer): Pair = space { sum(data.asIterable()) } to data.size public override suspend fun composeIntermediate(first: Pair, second: Pair): Pair = space { first.first + second.first } to (first.second + second.second) - public override suspend fun toResult(intermediate: Pair): T = - space { intermediate.first / intermediate.second } + public override suspend fun toResult(intermediate: Pair): T = space { + division(intermediate.first, intermediate.second) + } public companion object { //TODO replace with optimized version which respects overflow - public val real: Mean = Mean(RealField) - public val int: Mean = Mean(IntRing) - public val long: Mean = Mean(LongRing) + public val real: Mean = Mean(RealField) { sum, count -> sum / count } + public val int: Mean = Mean(IntRing) { sum, count -> sum / count } + public val long: Mean = Mean(LongRing) { sum, count -> sum / count } } } diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api index 462e065bf..ebb97b150 100644 --- a/kmath-viktor/api/kmath-viktor.api +++ b/kmath-viktor/api/kmath-viktor.api @@ -26,7 +26,7 @@ public final class space/kscience/kmath/viktor/ViktorBuffer : space/kscience/kma public final synthetic fun unbox-impl ()Lorg/jetbrains/bio/viktor/F64FlatArray; } -public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/kmath/nd/NDField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/RingWithNumbers { +public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/kmath/nd/NDField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { public fun ([I)V public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; public fun acos-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; @@ -55,8 +55,6 @@ public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/km public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun cosh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public fun div (DLspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public synthetic fun div (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; @@ -68,7 +66,7 @@ public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/km public fun divide (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; public fun exp-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun getElementContext ()Ljava/lang/Object; + public synthetic fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; public fun getElementContext ()Lspace/kscience/kmath/operations/RealField; public final fun getF64Buffer (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun getOne ()Ljava/lang/Object; @@ -96,11 +94,8 @@ public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/km public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public synthetic fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; public fun minus-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun multiply (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public fun multiply (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun multiply-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number-Q7Xurp0 (Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; public fun plus (DLspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; @@ -122,6 +117,8 @@ public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/km public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;D)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sin-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt index 8deda2544..218afcbef 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt @@ -4,8 +4,9 @@ import org.jetbrains.bio.viktor.F64Array import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.operations.NumbersAddOperations import space.kscience.kmath.operations.RealField -import space.kscience.kmath.operations.RingWithNumbers +import space.kscience.kmath.operations.ScaleOperations @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public inline class ViktorNDStructure(public val f64Buffer: F64Array) : MutableNDStructure { @@ -26,7 +27,8 @@ public fun F64Array.asStructure(): ViktorNDStructure = ViktorNDStructure(this) @OptIn(UnstableKMathAPI::class) @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public class ViktorNDField(public override val shape: IntArray) : NDField, - RingWithNumbers>, ExtendedField> { + NumbersAddOperations>, ExtendedField>, + ScaleOperations> { public val NDStructure.f64Buffer: F64Array get() = when { @@ -55,6 +57,8 @@ public class ViktorNDField(public override val shape: IntArray) : NDField.unaryMinus(): NDStructure = this * (-1) + public override fun NDStructure.map(transform: RealField.(Double) -> Double): ViktorNDStructure = F64Array(*this@ViktorNDField.shape).apply { this@ViktorNDField.strides.indices().forEach { index -> @@ -83,8 +87,8 @@ public class ViktorNDField(public override val shape: IntArray) : NDField, b: NDStructure): ViktorNDStructure = (a.f64Buffer + b.f64Buffer).asStructure() - public override fun multiply(a: NDStructure, k: Number): ViktorNDStructure = - (a.f64Buffer * k.toDouble()).asStructure() + public override fun scale(a: NDStructure, value: Double): ViktorNDStructure = + (a.f64Buffer * value.toDouble()).asStructure() public override inline fun NDStructure.plus(b: NDStructure): ViktorNDStructure = (f64Buffer + b.f64Buffer).asStructure() diff --git a/settings.gradle.kts b/settings.gradle.kts index cadbfd7ba..b4d7b3049 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,14 +1,15 @@ pluginManagement { repositories { + maven("https://repo.kotlin.link") + mavenLocal() gradlePluginPortal() jcenter() - maven("https://repo.kotlin.link") maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/kotlin/kotlinx") } - val toolsVersion = "0.8.1" - val kotlinVersion = "1.4.30" + val toolsVersion = "0.9.1" + val kotlinVersion = "1.4.31" plugins { id("kotlinx.benchmark") version "0.2.0-dev-20" From fe55856a26bd92c7389c57a17df9f908ea2cc343 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 9 Mar 2021 22:18:46 +0300 Subject: [PATCH 036/393] basic implements & refactor tensor structure & and new tensor algebra methods --- .../kmath/tensors/RealTensorAlgebra.kt | 137 ++++++++++++------ .../kscience/kmath/tensors/TensorAlgebra.kt | 14 +- .../kscience/kmath/tensors/TensorStrides.kt | 4 +- .../kscience/kmath/tensors/TensorStructure.kt | 23 +-- 4 files changed, 111 insertions(+), 67 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index cad01c4d0..13c57fc18 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -3,6 +3,8 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array +import kotlin.js.JsName +import kotlin.math.abs public class RealTensor( @@ -13,46 +15,80 @@ public class RealTensor( MutableNDBuffer( TensorStrides(shape), RealBuffer(buffer) - ) { - /* - * TODO: Andrei remove item() - */ - override fun item(): Double { - check(buffer.size > 0) { "The tensor is empty" } - return buffer[0] - } -} - + ) public class RealTensorAlgebra : TensorPartialDivisionAlgebra { + //rename to item? override fun RealTensor.value(): Double { - TODO("Andrei") + check(this.dimension == 0) { + // todo change message + "This tensor has shape ${shape.toList()}" + } + return this.buffer.array[0] + } + + override fun eye(n: Int): RealTensor { + val shape = intArrayOf(n, n) + val buffer = DoubleArray(n * n) { 0.0 } + val res = RealTensor(shape, buffer) + for (i in 0 until n) { + res[intArrayOf(i, i)] = 1.0 + } + return res + } + + override fun zeros(shape: IntArray): RealTensor { + TODO("Not yet implemented") + } + + override fun zeroesLike(other: RealTensor): RealTensor { + TODO("Not yet implemented") + } + + override fun ones(shape: IntArray): RealTensor { + TODO("Not yet implemented") + } + + override fun onesLike(shape: IntArray): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.copy(): RealTensor { + TODO("Not yet implemented") } override fun Double.plus(other: RealTensor): RealTensor { - val n = other.buffer.size - val arr = other.buffer.array - val res = DoubleArray(n) - for (i in 1..n) - res[i - 1] = arr[i - 1] + this - return RealTensor(other.shape, res) + //todo should be change with broadcasting + val resBuffer = DoubleArray(other.buffer.size) { i -> + other.buffer.array[i] + this + } + return RealTensor(other.shape, resBuffer) } - override fun RealTensor.plus(value: Double): RealTensor { - TODO("Andrei") - } + //todo should be change with broadcasting + override fun RealTensor.plus(value: Double): RealTensor = value + this override fun RealTensor.plus(other: RealTensor): RealTensor { - TODO("Andrei") + //todo should be change with broadcasting + val resBuffer = DoubleArray(this.buffer.size) { i -> + this.buffer.array[i] + other.buffer.array[i] + } + return RealTensor(this.shape, resBuffer) } override fun RealTensor.plusAssign(value: Double) { - TODO("Andrei") + //todo should be change with broadcasting + for (i in this.buffer.array.indices) { + this.buffer.array[i] += value + } } override fun RealTensor.plusAssign(other: RealTensor) { - TODO("Andrei") + //todo should be change with broadcasting + for (i in this.buffer.array.indices) { + this.buffer.array[i] += other.buffer.array[i] + } } override fun Double.minus(other: RealTensor): RealTensor { @@ -76,27 +112,43 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra + other.buffer.array[i] * this + } + return RealTensor(other.shape, resBuffer) } - override fun RealTensor.times(value: Double): RealTensor { - TODO("Andrei") - } + //todo should be change with broadcasting + override fun RealTensor.times(value: Double): RealTensor = value * this override fun RealTensor.times(other: RealTensor): RealTensor { - TODO("Andrei") + //todo should be change with broadcasting + val resBuffer = DoubleArray(this.buffer.size) { i -> + this.buffer.array[i] * other.buffer.array[i] + } + return RealTensor(this.shape, resBuffer) } override fun RealTensor.timesAssign(value: Double) { - TODO("Andrei") + //todo should be change with broadcasting + for (i in this.buffer.array.indices) { + this.buffer.array[i] *= value + } } override fun RealTensor.timesAssign(other: RealTensor) { - TODO("Andrei") + //todo should be change with broadcasting + for (i in this.buffer.array.indices) { + this.buffer.array[i] *= other.buffer.array[i] + } } override fun RealTensor.unaryMinus(): RealTensor { - TODO("Andrei") + val resBuffer = DoubleArray(this.buffer.size) { i -> + this.buffer.array[i].unaryMinus() + } + return RealTensor(this.shape, resBuffer) } override fun RealTensor.dot(other: RealTensor): RealTensor { @@ -124,11 +176,11 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { - /** - * Main first task for @AndreiKingsley - * Compare with the implementation of [LupDecomposition] - * and provide a common API - */ - TODO("Not yet implemented") + TODO() } - override fun lu_unpack(A_LU: RealTensor, pivots: RealTensor): Triple { + override fun luUnpack(A_LU: RealTensor, pivots: RealTensor): Triple { TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index b2586e1e9..6f42623e0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -5,6 +5,14 @@ public interface TensorAlgebra> { public fun TensorType.value(): T + public fun eye(n: Int): TensorType + public fun zeros(shape: IntArray): TensorType + public fun zeroesLike(other: TensorType): TensorType + public fun ones(shape: IntArray): TensorType + public fun onesLike(shape: IntArray): TensorType + + public fun TensorType.copy(): TensorType + public operator fun T.plus(other: TensorType): TensorType public operator fun TensorType.plus(value: T): TensorType public operator fun TensorType.plus(other: TensorType): TensorType @@ -42,7 +50,7 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/tensor_view.html public fun TensorType.view(shape: IntArray): TensorType - public fun TensorType.view_as(other: TensorType): TensorType + public fun TensorType.viewAs(other: TensorType): TensorType //https://pytorch.org/docs/stable/generated/torch.abs.html public fun TensorType.abs(): TensorType @@ -57,7 +65,9 @@ public interface TensorAlgebra> { public interface TensorPartialDivisionAlgebra> : TensorAlgebra { + public operator fun TensorType.div(value: T): TensorType public operator fun TensorType.div(other: TensorType): TensorType + public operator fun TensorType.divAssign(value: T) public operator fun TensorType.divAssign(other: TensorType) //https://pytorch.org/docs/stable/generated/torch.exp.html @@ -72,7 +82,7 @@ public interface TensorPartialDivisionAlgebra public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun lu_unpack(A_LU: TensorType, pivots: TensorType): Triple + public fun luUnpack(A_LU: TensorType, pivots: TensorType): Triple //https://pytorch.org/docs/stable/generated/torch.svd.html public fun TensorType.svd(): Triple diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt index 3ea8f4bf0..dbaefe907 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt @@ -5,7 +5,7 @@ import space.kscience.kmath.nd.offsetFromIndex import kotlin.math.max -inline public fun stridesFromShape(shape: IntArray): IntArray { +public inline fun stridesFromShape(shape: IntArray): IntArray { val nDim = shape.size val res = IntArray(nDim) if (nDim == 0) @@ -22,7 +22,7 @@ inline public fun stridesFromShape(shape: IntArray): IntArray { } -inline public fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { +public inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { val res = IntArray(nDim) var current = offset var strideIndex = 0 diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt index 3775ea2e5..5463877ce 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt @@ -2,26 +2,5 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDStructure -public interface TensorStructure : MutableNDStructure { +public typealias TensorStructure = MutableNDStructure - /* - * TODO: Andrei remove item() and value() - */ - public fun item(): T - - // A tensor can have empty shape, in which case it represents just a value - public fun value(): T { - checkIsValue() - return item() - } -} - -public inline fun TensorStructure.isValue(): Boolean { - return (dimension == 0) -} - -public inline fun TensorStructure.isNotValue(): Boolean = !this.isValue() - -public inline fun TensorStructure.checkIsValue(): Unit = check(this.isValue()) { - "This tensor has shape ${shape.toList()}" -} \ No newline at end of file From 3a37b88b5c4808107e2522d5f33eb07440169fb9 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 9 Mar 2021 21:13:48 +0000 Subject: [PATCH 037/393] Fixed getting value test for tensors --- .../space/kscience/kmath/tensors/RealTensorAlgebra.kt | 8 ++------ .../kotlin/space/kscience/kmath/tensors/TensorStrides.kt | 2 +- .../kotlin/space/kscience/kmath/tensors/TestRealTensor.kt | 4 ++-- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 13c57fc18..366acfb62 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -3,8 +3,6 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array -import kotlin.js.JsName -import kotlin.math.abs public class RealTensor( @@ -19,11 +17,9 @@ public class RealTensor( public class RealTensorAlgebra : TensorPartialDivisionAlgebra { - //rename to item? override fun RealTensor.value(): Double { - check(this.dimension == 0) { - // todo change message - "This tensor has shape ${shape.toList()}" + check(this.shape contentEquals intArrayOf(1)) { + "Inconsistent value for tensor of shape ${shape.toList()}" } return this.buffer.array[0] } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt index dbaefe907..0c10203f0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt @@ -48,5 +48,5 @@ public class TensorStrides(override val shape: IntArray): Strides indexFromOffset(offset, strides, shape.size) override val linearSize: Int - get() = shape.fold(1) { acc, i -> acc * i } + get() = shape.reduce(Int::times) } \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt index 7938eb864..d96b00baf 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt @@ -9,9 +9,9 @@ import kotlin.test.assertTrue class TestRealTensor { @Test - fun valueTest(){ + fun valueTest() = RealTensorAlgebra { val value = 12.5 - val tensor = RealTensor(IntArray(0), doubleArrayOf(value)) + val tensor = RealTensor(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } From 940718098dd588860e33aefde1d027a80dfdf61b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 10 Mar 2021 21:35:28 +0700 Subject: [PATCH 038/393] Revise benchmarks code Revise benchmarks code by using kotlinx.benchmark type aliases (it will simplify creating multiplatform benchmarks), using Blackhole class to consume results, moving all the constant state to private companion objects --- .../kmath/benchmarks/ArrayBenchmark.kt | 32 +++++++------ .../kmath/benchmarks/BufferBenchmark.kt | 10 ++--- .../kscience/kmath/benchmarks/DotBenchmark.kt | 27 +++++------ .../ExpressionsInterpretersBenchmark.kt | 37 ++++++++------- .../benchmarks/LinearAlgebraBenchmark.kt | 19 ++++---- .../kmath/benchmarks/NDFieldBenchmark.kt | 28 +++++++----- .../kmath/benchmarks/ViktorBenchmark.kt | 42 ++++++++++------- .../kmath/benchmarks/ViktorLogBenchmark.kt | 45 ++++++++++--------- 8 files changed, 134 insertions(+), 106 deletions(-) diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt index 535778844..43b698c03 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt @@ -1,34 +1,38 @@ package space.kscience.kmath.benchmarks -import org.openjdk.jmh.annotations.Benchmark -import org.openjdk.jmh.annotations.Scope -import org.openjdk.jmh.annotations.State +import kotlinx.benchmark.Benchmark +import kotlinx.benchmark.Blackhole +import kotlinx.benchmark.Scope +import kotlinx.benchmark.State import java.nio.IntBuffer @State(Scope.Benchmark) internal class ArrayBenchmark { @Benchmark - fun benchmarkArrayRead() { + fun benchmarkArrayRead(blackhole: Blackhole) { var res = 0 - for (i in 1..space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) res += space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.array[space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size - i] + for (i in 1..size) res += array[size - i] + blackhole.consume(res) } @Benchmark - fun benchmarkBufferRead() { + fun benchmarkBufferRead(blackhole: Blackhole) { var res = 0 - for (i in 1..space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) res += space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.arrayBuffer[space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size - i] + for (i in 1..size) res += arrayBuffer[size - i] + blackhole.consume(res) } @Benchmark - fun nativeBufferRead() { + fun nativeBufferRead(blackhole: Blackhole) { var res = 0 - for (i in 1..space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) res += space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.nativeBuffer[space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size - i] + for (i in 1..size) res += nativeBuffer[size - i] + blackhole.consume(res) } - companion object { - const val size: Int = 1000 - val array: IntArray = IntArray(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) { it } - val arrayBuffer: IntBuffer = IntBuffer.wrap(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.array) - val nativeBuffer: IntBuffer = IntBuffer.allocate(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size).also { for (i in 0 until space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) it.put(i, i) } + private companion object { + private const val size = 1000 + private val array = IntArray(size) { it } + private val arrayBuffer = IntBuffer.wrap(array) + private val nativeBuffer = IntBuffer.allocate(size).also { for (i in 0 until size) it.put(i, i) } } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt index 1afb4e52c..1c3bbab75 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.benchmarks -import org.openjdk.jmh.annotations.Benchmark -import org.openjdk.jmh.annotations.Scope -import org.openjdk.jmh.annotations.State +import kotlinx.benchmark.Benchmark +import kotlinx.benchmark.Scope +import kotlinx.benchmark.State import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.complex import space.kscience.kmath.structures.MutableBuffer @@ -28,7 +28,7 @@ internal class BufferBenchmark { } } - companion object { - const val size: Int = 100 + private companion object { + private const val size = 100 } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt index 39eeb24d3..93b5c5549 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt @@ -1,8 +1,9 @@ package space.kscience.kmath.benchmarks import kotlinx.benchmark.Benchmark -import org.openjdk.jmh.annotations.Scope -import org.openjdk.jmh.annotations.State +import kotlinx.benchmark.Blackhole +import kotlinx.benchmark.Scope +import kotlinx.benchmark.State import space.kscience.kmath.commons.linear.CMMatrixContext import space.kscience.kmath.ejml.EjmlMatrixContext import space.kscience.kmath.linear.BufferMatrixContext @@ -17,7 +18,7 @@ import kotlin.random.Random internal class DotBenchmark { companion object { val random = Random(12224) - val dim = 1000 + const val dim = 1000 //creating invertible matrix val matrix1 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } @@ -31,37 +32,37 @@ internal class DotBenchmark { } @Benchmark - fun cmDot() { + fun cmDot(blackhole: Blackhole) { CMMatrixContext { - cmMatrix1 dot cmMatrix2 + blackhole.consume(cmMatrix1 dot cmMatrix2) } } @Benchmark - fun ejmlDot() { + fun ejmlDot(blackhole: Blackhole) { EjmlMatrixContext { - ejmlMatrix1 dot ejmlMatrix2 + blackhole.consume(ejmlMatrix1 dot ejmlMatrix2) } } @Benchmark - fun ejmlDotWithConversion() { + fun ejmlDotWithConversion(blackhole: Blackhole) { EjmlMatrixContext { - matrix1 dot matrix2 + blackhole.consume(matrix1 dot matrix2) } } @Benchmark - fun bufferedDot() { + fun bufferedDot(blackhole: Blackhole) { BufferMatrixContext(RealField, Buffer.Companion::real).invoke { - matrix1 dot matrix2 + blackhole.consume(matrix1 dot matrix2) } } @Benchmark - fun realDot() { + fun realDot(blackhole: Blackhole) { RealMatrixContext { - matrix1 dot matrix2 + blackhole.consume(matrix1 dot matrix2) } } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index a9c0fe703..9c150f074 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -1,64 +1,62 @@ package space.kscience.kmath.benchmarks -import org.openjdk.jmh.annotations.Benchmark -import org.openjdk.jmh.annotations.Scope -import org.openjdk.jmh.annotations.State +import kotlinx.benchmark.Benchmark +import kotlinx.benchmark.Blackhole +import kotlinx.benchmark.Scope +import kotlinx.benchmark.State import space.kscience.kmath.asm.compile import space.kscience.kmath.ast.mstInField import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.expressionInField import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.symbol -import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.bindSymbol import kotlin.random.Random @State(Scope.Benchmark) internal class ExpressionsInterpretersBenchmark { - private val algebra: Field = RealField - val x by symbol - @Benchmark - fun functionalExpression() { + fun functionalExpression(blackhole: Blackhole) { val expr = algebra.expressionInField { val x = bindSymbol(x) x * const(2.0) + const(2.0) / x - const(16.0) } - invokeAndSum(expr) + invokeAndSum(expr, blackhole) } @Benchmark - fun mstExpression() { + fun mstExpression(blackhole: Blackhole) { val expr = algebra.mstInField { val x = bindSymbol(x) x * 2.0 + 2.0 / x - 16.0 } - invokeAndSum(expr) + invokeAndSum(expr, blackhole) } @Benchmark - fun asmExpression() { + fun asmExpression(blackhole: Blackhole) { val expr = algebra.mstInField { val x = bindSymbol(x) x * 2.0 + 2.0 / x - 16.0 }.compile() - invokeAndSum(expr) + invokeAndSum(expr, blackhole) } @Benchmark - fun rawExpression() { + fun rawExpression(blackhole: Blackhole) { val expr = Expression { args -> val x = args.getValue(x) x * 2.0 + 2.0 / x - 16.0 } - invokeAndSum(expr) + + invokeAndSum(expr, blackhole) } - private fun invokeAndSum(expr: Expression) { + private fun invokeAndSum(expr: Expression, blackhole: Blackhole) { val random = Random(0) var sum = 0.0 @@ -66,6 +64,11 @@ internal class ExpressionsInterpretersBenchmark { sum += expr(x to random.nextDouble()) } - println(sum) + blackhole.consume(sum) + } + + private companion object { + private val algebra = RealField + private val x by symbol } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt index 22e735e12..30cb6c0b9 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt @@ -1,8 +1,9 @@ package space.kscience.kmath.benchmarks import kotlinx.benchmark.Benchmark -import org.openjdk.jmh.annotations.Scope -import org.openjdk.jmh.annotations.State +import kotlinx.benchmark.Blackhole +import kotlinx.benchmark.Scope +import kotlinx.benchmark.State import space.kscience.kmath.commons.linear.CMMatrixContext import space.kscience.kmath.commons.linear.CMMatrixContext.dot import space.kscience.kmath.commons.linear.inverse @@ -18,7 +19,7 @@ import kotlin.random.Random internal class LinearAlgebraBenchmark { companion object { val random = Random(1224) - val dim = 100 + const val dim = 100 //creating invertible matrix val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } @@ -27,21 +28,21 @@ internal class LinearAlgebraBenchmark { } @Benchmark - fun kmathLupInversion() { - MatrixContext.real.inverseWithLup(matrix) + fun kmathLupInversion(blackhole: Blackhole) { + blackhole.consume(MatrixContext.real.inverseWithLup(matrix)) } @Benchmark - fun cmLUPInversion() { + fun cmLUPInversion(blackhole: Blackhole) { with(CMMatrixContext) { - inverse(matrix) + blackhole.consume(inverse(matrix)) } } @Benchmark - fun ejmlInverse() { + fun ejmlInverse(blackhole: Blackhole) { with(EjmlMatrixContext) { - inverse(matrix) + blackhole.consume(inverse(matrix)) } } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt index 5bcc09cdb..aeee0dafe 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -1,8 +1,9 @@ package space.kscience.kmath.benchmarks -import org.openjdk.jmh.annotations.Benchmark -import org.openjdk.jmh.annotations.Scope -import org.openjdk.jmh.annotations.State +import kotlinx.benchmark.Benchmark +import kotlinx.benchmark.Blackhole +import kotlinx.benchmark.Scope +import kotlinx.benchmark.State import space.kscience.kmath.nd.* import space.kscience.kmath.operations.RealField import space.kscience.kmath.structures.Buffer @@ -10,35 +11,38 @@ import space.kscience.kmath.structures.Buffer @State(Scope.Benchmark) internal class NDFieldBenchmark { @Benchmark - fun autoFieldAdd() { + fun autoFieldAdd(blackhole: Blackhole) { with(autoField) { var res: NDStructure = one repeat(n) { res += one } + blackhole.consume(res) } } @Benchmark - fun specializedFieldAdd() { + fun specializedFieldAdd(blackhole: Blackhole) { with(specializedField) { var res: NDStructure = one repeat(n) { res += 1.0 } + blackhole.consume(res) } } @Benchmark - fun boxingFieldAdd() { + fun boxingFieldAdd(blackhole: Blackhole) { with(genericField) { var res: NDStructure = one repeat(n) { res += 1.0 } + blackhole.consume(res) } } - companion object { - const val dim: Int = 1000 - const val n: Int = 100 - val autoField = NDAlgebra.auto(RealField, dim, dim) - val specializedField: RealNDField = NDAlgebra.real(dim, dim) - val genericField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim) + private companion object { + private const val dim = 1000 + private const val n = 100 + private val autoField = NDAlgebra.auto(RealField, dim, dim) + private val specializedField = NDAlgebra.real(dim, dim) + private val genericField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim) } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt index 370258bc6..c511173a9 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt @@ -1,51 +1,61 @@ package space.kscience.kmath.benchmarks +import kotlinx.benchmark.Benchmark +import kotlinx.benchmark.Blackhole +import kotlinx.benchmark.Scope +import kotlinx.benchmark.State import org.jetbrains.bio.viktor.F64Array -import org.openjdk.jmh.annotations.Benchmark -import org.openjdk.jmh.annotations.Scope -import org.openjdk.jmh.annotations.State -import space.kscience.kmath.nd.* +import space.kscience.kmath.nd.NDAlgebra +import space.kscience.kmath.nd.NDStructure +import space.kscience.kmath.nd.auto +import space.kscience.kmath.nd.real import space.kscience.kmath.operations.RealField import space.kscience.kmath.viktor.ViktorNDField @State(Scope.Benchmark) internal class ViktorBenchmark { - final val dim: Int = 1000 - final val n: Int = 100 - - // automatically build context most suited for given type. - final val autoField: NDField = NDAlgebra.auto(RealField, dim, dim) - final val realField: RealNDField = NDAlgebra.real(dim, dim) - final val viktorField: ViktorNDField = ViktorNDField(dim, dim) - @Benchmark - fun automaticFieldAddition() { + fun automaticFieldAddition(blackhole: Blackhole) { with(autoField) { var res: NDStructure = one repeat(n) { res += 1.0 } + blackhole.consume(res) } } @Benchmark - fun realFieldAddition() { + fun realFieldAddition(blackhole: Blackhole) { with(realField) { var res: NDStructure = one repeat(n) { res += 1.0 } + blackhole.consume(res) } } @Benchmark - fun viktorFieldAddition() { + fun viktorFieldAddition(blackhole: Blackhole) { with(viktorField) { var res = one repeat(n) { res += 1.0 } + blackhole.consume(res) } } @Benchmark - fun rawViktor() { + fun rawViktor(blackhole: Blackhole) { val one = F64Array.full(init = 1.0, shape = intArrayOf(dim, dim)) var res = one repeat(n) { res = res + one } + blackhole.consume(res) + } + + private companion object { + private const val dim = 1000 + private const val n = 100 + + // automatically build context most suited for given type. + private val autoField = NDAlgebra.auto(RealField, dim, dim) + private val realField = NDAlgebra.real(dim, dim) + private val viktorField = ViktorNDField(dim, dim) } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt index 9f99b002a..c48c86af9 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt @@ -1,48 +1,53 @@ package space.kscience.kmath.benchmarks +import kotlinx.benchmark.Benchmark +import kotlinx.benchmark.Blackhole +import kotlinx.benchmark.Scope +import kotlinx.benchmark.State import org.jetbrains.bio.viktor.F64Array -import org.openjdk.jmh.annotations.Benchmark -import org.openjdk.jmh.annotations.Scope -import org.openjdk.jmh.annotations.State -import space.kscience.kmath.nd.* +import space.kscience.kmath.nd.NDAlgebra +import space.kscience.kmath.nd.auto +import space.kscience.kmath.nd.real import space.kscience.kmath.operations.RealField import space.kscience.kmath.viktor.ViktorNDField @State(Scope.Benchmark) internal class ViktorLogBenchmark { - final val dim: Int = 1000 - final val n: Int = 100 - - // automatically build context most suited for given type. - final val autoField: NDField = NDAlgebra.auto(RealField, dim, dim) - final val realField: RealNDField = NDAlgebra.real(dim, dim) - final val viktorField: ViktorNDField = ViktorNDField(intArrayOf(dim, dim)) - - @Benchmark - fun realFieldLog() { + fun realFieldLog(blackhole: Blackhole) { with(realField) { val fortyTwo = produce { 42.0 } var res = one repeat(n) { res = ln(fortyTwo) } + blackhole.consume(res) } } @Benchmark - fun viktorFieldLog() { + fun viktorFieldLog(blackhole: Blackhole) { with(viktorField) { val fortyTwo = produce { 42.0 } var res = one repeat(n) { res = ln(fortyTwo) } + blackhole.consume(res) } } @Benchmark - fun rawViktorLog() { + fun rawViktorLog(blackhole: Blackhole) { val fortyTwo = F64Array.full(dim, dim, init = 42.0) - var res: F64Array - repeat(n) { - res = fortyTwo.log() - } + lateinit var res: F64Array + repeat(n) { res = fortyTwo.log() } + blackhole.consume(res) + } + + private companion object { + private const val dim = 1000 + private const val n = 100 + + // automatically build context most suited for given type. + private val autoField = NDAlgebra.auto(RealField, dim, dim) + private val realField = NDAlgebra.real(dim, dim) + private val viktorField = ViktorNDField(intArrayOf(dim, dim)) } } From 6a5ca2a115570c404b7fa0be7885cd2d539e60e5 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 10 Mar 2021 18:02:04 +0300 Subject: [PATCH 039/393] Code review. --- CHANGELOG.md | 2 +- build.gradle.kts | 1 + .../space/kscience/kmath/ast/expressions.kt | 3 +- .../kmath/linear/RealMatrixContext.kt | 12 ++- .../kmath/operations/NumericAlgebra.kt | 2 +- .../kscience/kmath/functions/Polynomial.kt | 6 +- .../kmath/interpolation/SplineInterpolator.kt | 4 +- .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 100 +++++++----------- .../kmath/viktor/ViktorNDStructure.kt | 2 +- 9 files changed, 58 insertions(+), 74 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db3b65024..595cd3bbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,8 @@ ## [Unreleased] ### Added -- Intrinsic value `two` for ExtendedField to work with hyperbolic functions - ScaleOperations interface +- Field extends ScaleOperations ### Changed - Exponential operations merged with hyperbolic functions diff --git a/build.gradle.kts b/build.gradle.kts index 41e8a3468..113107f69 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,6 +34,7 @@ readme { ksciencePublish { github("kmath") space() + sonatype() } apiValidation { diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt index 8d6851ef8..1cafe30c1 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt @@ -1,12 +1,11 @@ package space.kscience.kmath.ast -import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.RealField fun main() { val expr = RealField.mstInField { val x = bindSymbol("x") - x * 2.0 + 2.0 * one / x - 16.0 + x * 2.0 + number(2.0) / x - 16.0 } repeat(10000000) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt index a53f0837f..dbccb7536 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt @@ -1,8 +1,9 @@ package space.kscience.kmath.linear +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.structures.RealBuffer -public object RealMatrixContext : MatrixContext> { +public object RealMatrixContext : MatrixContext>, ScaleOperations> { public override fun produce( rows: Int, @@ -58,10 +59,13 @@ public object RealMatrixContext : MatrixContext> { } } - override fun Matrix.times(value: Double): BufferMatrix { - val bufferMatrix = toBufferMatrix() - return produce(rowNum, colNum) { i, j -> bufferMatrix[i, j] * value } + override fun scale(a: Matrix, value: Double): BufferMatrix { + val bufferMatrix = a.toBufferMatrix() + return produce(a.rowNum, a.colNum) { i, j -> bufferMatrix[i, j] * value } } + + override fun Matrix.times(value: Double): BufferMatrix = scale(this, value) + // // override fun multiply(a: Matrix, k: Number): BufferMatrix { // val aBufferMatrix = a.toBufferMatrix() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt index 187261b1d..5f6ec869a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt @@ -86,7 +86,7 @@ public interface NumericAlgebra : Algebra { */ public interface ScaleOperations : Algebra { /** - * Scaling of element by scalar. + * Scaling an element by a scalar. * * @param a the multiplier. * @param value the multiplicand. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 7416069bd..9141fa7b9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -42,9 +42,9 @@ public fun > Polynomial.asFunction(ring: C): (T) -> T = /** * An algebra for polynomials */ -public class PolynomialSpace( +public class PolynomialSpace( private val ring: C, -) : Space>, ScaleOperations> where C: Ring, C: ScaleOperations{ +) : Space>, ScaleOperations> where C : Ring, C : ScaleOperations { public override val zero: Polynomial = Polynomial(emptyList()) override fun Polynomial.unaryMinus(): Polynomial = with(ring) { @@ -67,7 +67,7 @@ public class PolynomialSpace( public operator fun Polynomial.invoke(arg: T): T = value(ring, arg) } -public inline fun C.polynomial(block: PolynomialSpace.() -> R): R where C: Ring, C: ScaleOperations{ +public inline fun C.polynomial(block: PolynomialSpace.() -> R): R where C : Ring, C : ScaleOperations { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return PolynomialSpace(this).block() } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index 78d6e0d0c..ddbe743f0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -11,8 +11,8 @@ import space.kscience.kmath.structures.MutableBufferFactory * Generic spline interpolator. Not recommended for performance critical places, use platform-specific and type specific ones. * Based on https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/SplineInterpolator.java */ -public class SplineInterpolator, F : Field>( - public override val algebra: F, +public class SplineInterpolator>( + public override val algebra: Field, public val bufferFactory: MutableBufferFactory, ) : PolynomialInterpolator { //TODO possibly optimize zeroed buffers diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index 11e7b73e4..dea74abdc 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -80,21 +80,17 @@ public interface Nd4jArraySpace> : NDSpace, Nd4jArrayAlgeb public override val zero: Nd4jArrayStructure get() = Nd4j.zeros(*shape).wrap() - public override fun add(a: NDStructure, b: NDStructure): Nd4jArrayStructure { - return a.ndArray.add(b.ndArray).wrap() - } + public override fun add(a: NDStructure, b: NDStructure): Nd4jArrayStructure = + a.ndArray.add(b.ndArray).wrap() - public override operator fun NDStructure.minus(b: NDStructure): Nd4jArrayStructure { - return ndArray.sub(b.ndArray).wrap() - } + public override operator fun NDStructure.minus(b: NDStructure): Nd4jArrayStructure = + ndArray.sub(b.ndArray).wrap() - public override operator fun NDStructure.unaryMinus(): Nd4jArrayStructure { - return ndArray.neg().wrap() - } + public override operator fun NDStructure.unaryMinus(): Nd4jArrayStructure = + ndArray.neg().wrap() - public fun multiply(a: NDStructure, k: Number): Nd4jArrayStructure { - return a.ndArray.mul(k).wrap() - } + public fun multiply(a: NDStructure, k: Number): Nd4jArrayStructure = + a.ndArray.mul(k).wrap() } /** @@ -109,9 +105,8 @@ public interface Nd4jArrayRing> : NDRing, Nd4jArraySpace get() = Nd4j.ones(*shape).wrap() - public override fun multiply(a: NDStructure, b: NDStructure): Nd4jArrayStructure { - return a.ndArray.mul(b.ndArray).wrap() - } + public override fun multiply(a: NDStructure, b: NDStructure): Nd4jArrayStructure = + a.ndArray.mul(b.ndArray).wrap() // // public override operator fun Nd4jArrayStructure.minus(b: Number): Nd4jArrayStructure { // check(this) @@ -250,33 +245,26 @@ public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArra public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asFloatStructure() - override fun scale(a: NDStructure, value: Double): NDStructure { - return a.ndArray.mul(value).wrap() - } + override fun scale(a: NDStructure, value: Double): NDStructure = + a.ndArray.mul(value).wrap() - public override operator fun NDStructure.div(arg: Float): Nd4jArrayStructure { - return ndArray.div(arg).wrap() - } + public override operator fun NDStructure.div(arg: Float): Nd4jArrayStructure = + ndArray.div(arg).wrap() - public override operator fun NDStructure.plus(arg: Float): Nd4jArrayStructure { - return ndArray.add(arg).wrap() - } + public override operator fun NDStructure.plus(arg: Float): Nd4jArrayStructure = + ndArray.add(arg).wrap() - public override operator fun NDStructure.minus(arg: Float): Nd4jArrayStructure { - return ndArray.sub(arg).wrap() - } + public override operator fun NDStructure.minus(arg: Float): Nd4jArrayStructure = + ndArray.sub(arg).wrap() - public override operator fun NDStructure.times(arg: Float): Nd4jArrayStructure { - return ndArray.mul(arg).wrap() - } + public override operator fun NDStructure.times(arg: Float): Nd4jArrayStructure = + ndArray.mul(arg).wrap() - public override operator fun Float.div(arg: NDStructure): Nd4jArrayStructure { - return arg.ndArray.rdiv(this).wrap() - } + public override operator fun Float.div(arg: NDStructure): Nd4jArrayStructure = + arg.ndArray.rdiv(this).wrap() - public override operator fun Float.minus(arg: NDStructure): Nd4jArrayStructure { - return arg.ndArray.rsub(this).wrap() - } + public override operator fun Float.minus(arg: NDStructure): Nd4jArrayStructure = + arg.ndArray.rsub(this).wrap() } /** @@ -288,21 +276,17 @@ public class IntNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRi public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asIntStructure() - public override operator fun NDStructure.plus(arg: Int): Nd4jArrayStructure { - return ndArray.add(arg).wrap() - } + public override operator fun NDStructure.plus(arg: Int): Nd4jArrayStructure = + ndArray.add(arg).wrap() - public override operator fun NDStructure.minus(arg: Int): Nd4jArrayStructure { - return ndArray.sub(arg).wrap() - } + public override operator fun NDStructure.minus(arg: Int): Nd4jArrayStructure = + ndArray.sub(arg).wrap() - public override operator fun NDStructure.times(arg: Int): Nd4jArrayStructure { - return ndArray.mul(arg).wrap() - } + public override operator fun NDStructure.times(arg: Int): Nd4jArrayStructure = + ndArray.mul(arg).wrap() - public override operator fun Int.minus(arg: NDStructure): Nd4jArrayStructure { - return arg.ndArray.rsub(this).wrap() - } + public override operator fun Int.minus(arg: NDStructure): Nd4jArrayStructure = + arg.ndArray.rsub(this).wrap() } /** @@ -314,19 +298,15 @@ public class LongNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayR public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asLongStructure() - public override operator fun NDStructure.plus(arg: Long): Nd4jArrayStructure { - return ndArray.add(arg).wrap() - } + public override operator fun NDStructure.plus(arg: Long): Nd4jArrayStructure = + ndArray.add(arg).wrap() - public override operator fun NDStructure.minus(arg: Long): Nd4jArrayStructure { - return ndArray.sub(arg).wrap() - } + public override operator fun NDStructure.minus(arg: Long): Nd4jArrayStructure = + ndArray.sub(arg).wrap() - public override operator fun NDStructure.times(arg: Long): Nd4jArrayStructure { - return ndArray.mul(arg).wrap() - } + public override operator fun NDStructure.times(arg: Long): Nd4jArrayStructure = + ndArray.mul(arg).wrap() - public override operator fun Long.minus(arg: NDStructure): Nd4jArrayStructure { - return arg.ndArray.rsub(this).wrap() - } + public override operator fun Long.minus(arg: NDStructure): Nd4jArrayStructure = + arg.ndArray.rsub(this).wrap() } diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt index 218afcbef..f5697cea2 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt @@ -57,7 +57,7 @@ public class ViktorNDField(public override val shape: IntArray) : NDField.unaryMinus(): NDStructure = this * (-1) + override fun NDStructure.unaryMinus(): NDStructure = -1 * this public override fun NDStructure.map(transform: RealField.(Double) -> Double): ViktorNDStructure = F64Array(*this@ViktorNDField.shape).apply { From fe95c4e48ed60716b60e446d26aca6083a7a83a2 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 10 Mar 2021 18:20:23 +0300 Subject: [PATCH 040/393] Code review. --- .../kotlin/space/kscience/kmath/ast/expressions.kt | 1 + kmath-core/api/kmath-core.api | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt index 1cafe30c1..c342fc3ef 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.ast +import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.RealField fun main() { diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 0efe430ad..da4725428 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -697,7 +697,7 @@ public abstract interface class space/kscience/kmath/linear/QRDecompositionFeatu public abstract fun getR ()Lspace/kscience/kmath/nd/Structure2D; } -public final class space/kscience/kmath/linear/RealMatrixContext : space/kscience/kmath/linear/MatrixContext { +public final class space/kscience/kmath/linear/RealMatrixContext : space/kscience/kmath/linear/MatrixContext, space/kscience/kmath/operations/ScaleOperations { public static final field INSTANCE Lspace/kscience/kmath/linear/RealMatrixContext; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; @@ -706,6 +706,8 @@ public final class space/kscience/kmath/linear/RealMatrixContext : space/kscienc public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun div (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; @@ -717,9 +719,15 @@ public final class space/kscience/kmath/linear/RealMatrixContext : space/kscienc public fun point (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; public fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/Structure2D; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/nd/Structure2D;D)Lspace/kscience/kmath/linear/BufferMatrix; public fun times (DLspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; + public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public fun times (Lspace/kscience/kmath/nd/Structure2D;D)Lspace/kscience/kmath/linear/BufferMatrix; + public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public synthetic fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; public final fun toBufferMatrix (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; From 39b41cc2ae0b8c7071c42fe50b8cd08b1016e15f Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 10 Mar 2021 22:40:43 +0700 Subject: [PATCH 041/393] Fix #223 --- .../kotlin/space/kscience/kmath/operations/Algebra.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 572f7089a..6bb7d5ed7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -188,7 +188,7 @@ public interface SpaceOperations : Algebra { public operator fun Number.times(b: T): T = b * this public override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) { - PLUS_OPERATION -> { arg -> arg } + PLUS_OPERATION -> { arg -> +arg } MINUS_OPERATION -> { arg -> -arg } else -> super.unaryOperationFunction(operation) } From 522f39cef3f75efe11d5e323a3ada955da9d6f7a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 10 Mar 2021 22:09:19 +0300 Subject: [PATCH 042/393] replace Space by Group --- CHANGELOG.md | 1 + .../space/kscience/kmath/ast/MstAlgebra.kt | 34 +-- .../space/kscience/kmath/ast/MstExpression.kt | 10 +- .../TestESTreeConsistencyWithInterpreter.kt | 4 +- .../kotlin/space/kscience/kmath/ast/parser.kt | 8 +- .../asm/TestAsmConsistencyWithInterpreter.kt | 4 +- kmath-core/api/kmath-core.api | 260 +++++++++--------- .../FunctionalExpressionAlgebra.kt | 20 +- .../kmath/expressions/expressionBuilders.kt | 8 +- .../kscience/kmath/linear/MatrixContext.kt | 2 +- .../kscience/kmath/linear/VectorSpace.kt | 14 +- .../space/kscience/kmath/misc/cumulative.kt | 8 +- .../kscience/kmath/nd/BufferNDAlgebra.kt | 14 +- .../space/kscience/kmath/nd/NDAlgebra.kt | 20 +- .../kscience/kmath/operations/Algebra.kt | 11 +- .../kmath/operations/AlgebraElements.kt | 6 +- .../kmath/operations/NumericAlgebra.kt | 2 +- .../kmath/operations/algebraExtensions.kt | 30 +- .../kscience/kmath/testutils/SpaceVerifier.kt | 4 +- .../space/kscience/kmath/chains/flowExtra.kt | 10 +- .../kscience/kmath/functions/Polynomial.kt | 4 +- .../kscience/kmath/geometry/GeometrySpace.kt | 4 +- .../space/kscience/kmath/histogram/Counter.kt | 4 +- .../kmath/histogram/IndexedHistogramSpace.kt | 4 +- .../kmath/histogram/TreeHistogramSpace.kt | 4 +- .../kmath/histogram/UnivariateHistogram.kt | 4 +- .../kmath/kotlingrad/ScalarsAdapters.kt | 8 +- .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 6 +- .../kscience/kmath/stat/SamplerAlgebra.kt | 6 +- .../space/kscience/kmath/stat/Statistic.kt | 2 +- 30 files changed, 258 insertions(+), 258 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 595cd3bbc..a172eb69a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Changed - Exponential operations merged with hyperbolic functions +- Space is replaced by Group. Space is reserved for vector spaces. ### Deprecated diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt index 047ee187d..a65027147 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt @@ -18,22 +18,22 @@ public object MstAlgebra : NumericAlgebra { } /** - * [Space] over [MST] nodes. + * [Group] over [MST] nodes. */ -public object MstSpace : Space, NumericAlgebra, ScaleOperations { +public object MstGroup : Group, NumericAlgebra, ScaleOperations { public override val zero: MST.Numeric = number(0.0) public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value) - public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b) + public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(GroupOperations.PLUS_OPERATION)(a, b) public override operator fun MST.unaryPlus(): MST.Unary = - unaryOperationFunction(SpaceOperations.PLUS_OPERATION)(this) + unaryOperationFunction(GroupOperations.PLUS_OPERATION)(this) public override operator fun MST.unaryMinus(): MST.Unary = - unaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this) + unaryOperationFunction(GroupOperations.MINUS_OPERATION)(this) public override operator fun MST.minus(b: MST): MST.Binary = - binaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this, b) + binaryOperationFunction(GroupOperations.MINUS_OPERATION)(this, b) public override fun scale(a: MST, value: Double): MST.Binary = binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(value)) @@ -50,25 +50,25 @@ public object MstSpace : Space, NumericAlgebra, ScaleOperations { */ @OptIn(UnstableKMathAPI::class) public object MstRing : Ring, NumbersAddOperations, ScaleOperations { - public override val zero: MST.Numeric = MstSpace.zero + public override val zero: MST.Numeric = MstGroup.zero public override val one: MST.Numeric = number(1.0) - public override fun number(value: Number): MST.Numeric = MstSpace.number(value) - public override fun bindSymbol(value: String): MST.Symbolic = MstSpace.bindSymbol(value) - public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b) + public override fun number(value: Number): MST.Numeric = MstGroup.number(value) + public override fun bindSymbol(value: String): MST.Symbolic = MstGroup.bindSymbol(value) + public override fun add(a: MST, b: MST): MST.Binary = MstGroup.add(a, b) public override fun scale(a: MST, value: Double): MST.Binary = - MstSpace.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstSpace.number(value)) + MstGroup.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstGroup.number(value)) public override fun multiply(a: MST, b: MST): MST.Binary = binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b) - public override operator fun MST.unaryPlus(): MST.Unary = MstSpace { +this@unaryPlus } - public override operator fun MST.unaryMinus(): MST.Unary = MstSpace { -this@unaryMinus } - public override operator fun MST.minus(b: MST): MST.Binary = MstSpace { this@minus - b } + public override operator fun MST.unaryPlus(): MST.Unary = MstGroup { +this@unaryPlus } + public override operator fun MST.unaryMinus(): MST.Unary = MstGroup { -this@unaryMinus } + public override operator fun MST.minus(b: MST): MST.Binary = MstGroup { this@minus - b } public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = - MstSpace.binaryOperationFunction(operation) + MstGroup.binaryOperationFunction(operation) public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = MstAlgebra.unaryOperationFunction(operation) @@ -88,7 +88,7 @@ public object MstField : Field, NumbersAddOperations, ScaleOperations< public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b) public override fun scale(a: MST, value: Double): MST.Binary = - MstSpace.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstSpace.number(value)) + MstGroup.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstGroup.number(value)) public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b) public override fun divide(a: MST, b: MST): MST.Binary = @@ -129,7 +129,7 @@ public object MstExtendedField : ExtendedField, NumericAlgebra { public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b) public override fun scale(a: MST, value: Double): MST = - binaryOperation(SpaceOperations.PLUS_OPERATION, a, number(value)) + binaryOperation(GroupOperations.PLUS_OPERATION, a, number(value)) public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b) public override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt index 412dde32c..3a598fb8c 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt @@ -54,13 +54,13 @@ public inline fun , E : Algebra> A.mst( ): MstExpression = MstExpression(this, mstAlgebra.block()) /** - * Builds [MstExpression] over [Space]. + * Builds [MstExpression] over [Group]. * * @author Alexander Nozik */ -public inline fun > A.mstInSpace(block: MstSpace.() -> MST): MstExpression { +public inline fun > A.mstInSpace(block: MstGroup.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return MstExpression(this, MstSpace.block()) + return MstExpression(this, MstGroup.block()) } /** @@ -94,11 +94,11 @@ public inline fun > A.mstInExtendedField(b } /** - * Builds [MstExpression] over [FunctionalExpressionSpace]. + * Builds [MstExpression] over [FunctionalExpressionGroup]. * * @author Alexander Nozik */ -public inline fun > FunctionalExpressionSpace.mstInSpace(block: MstSpace.() -> MST): MstExpression { +public inline fun > FunctionalExpressionGroup.mstInSpace(block: MstGroup.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return algebra.mstInSpace(block) } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt index c91cc4daf..34e9dd945 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt @@ -12,7 +12,7 @@ import kotlin.test.assertEquals internal class TestESTreeConsistencyWithInterpreter { @Test fun mstSpace() { - val res1 = MstSpace.mstInSpace { + val res1 = MstGroup.mstInSpace { binaryOperationFunction("+")( unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (scale( @@ -25,7 +25,7 @@ internal class TestESTreeConsistencyWithInterpreter { ) + bindSymbol("x") + zero }("x" to MST.Numeric(2)) - val res2 = MstSpace.mstInSpace { + val res2 = MstGroup.mstInSpace { binaryOperationFunction("+")( unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (scale( diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt index be4aff34f..9a38ce81a 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt @@ -14,9 +14,9 @@ import com.github.h0tk3y.betterParse.lexer.regexToken import com.github.h0tk3y.betterParse.parser.ParseResult import com.github.h0tk3y.betterParse.parser.Parser import space.kscience.kmath.operations.FieldOperations +import space.kscience.kmath.operations.GroupOperations import space.kscience.kmath.operations.PowerOperations import space.kscience.kmath.operations.RingOperations -import space.kscience.kmath.operations.SpaceOperations /** * better-parse implementation of grammar defined in the ArithmeticsEvaluator.g4. @@ -55,7 +55,7 @@ public object ArithmeticsEvaluator : Grammar() { .or(binaryFunction) .or(unaryFunction) .or(singular) - .or(-minus and parser(ArithmeticsEvaluator::term) map { MST.Unary(SpaceOperations.MINUS_OPERATION, it) }) + .or(-minus and parser(ArithmeticsEvaluator::term) map { MST.Unary(GroupOperations.MINUS_OPERATION, it) }) .or(-lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar) private val powChain: Parser by leftAssociative(term = term, operator = pow) { a, _, b -> @@ -77,9 +77,9 @@ public object ArithmeticsEvaluator : Grammar() { operator = plus or minus use TokenMatch::type ) { a, op, b -> if (op == plus) - MST.Binary(SpaceOperations.PLUS_OPERATION, a, b) + MST.Binary(GroupOperations.PLUS_OPERATION, a, b) else - MST.Binary(SpaceOperations.MINUS_OPERATION, a, b) + MST.Binary(GroupOperations.MINUS_OPERATION, a, b) } override val rootParser: Parser by subSumChain diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt index 5c6297f3f..4be2ee331 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt @@ -12,7 +12,7 @@ import kotlin.test.assertEquals internal class TestAsmConsistencyWithInterpreter { @Test fun mstSpace() { - val res1 = MstSpace.mstInSpace { + val res1 = MstGroup.mstInSpace { binaryOperationFunction("+")( unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (scale( @@ -25,7 +25,7 @@ internal class TestAsmConsistencyWithInterpreter { ) + bindSymbol("x") + zero }("x" to MST.Numeric(2)) - val res2 = MstSpace.mstInSpace { + val res2 = MstGroup.mstInSpace { binaryOperationFunction("+")( unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (scale( diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index da4725428..eae91c985 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -52,7 +52,7 @@ public final class space/kscience/kmath/expressions/ExpressionBuildersKt { public static final fun extendedFieldExpression (Lspace/kscience/kmath/operations/ExtendedField;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; public static final fun fieldExpression (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; public static final fun ringExpression (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; - public static final fun spaceExpression (Lspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; + public static final fun spaceExpression (Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; } public final class space/kscience/kmath/expressions/ExpressionKt { @@ -91,7 +91,7 @@ public final class space/kscience/kmath/expressions/FunctionalExpressionAlgebraK public static final fun expressionInExtendedField (Lspace/kscience/kmath/operations/ExtendedField;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; public static final fun expressionInField (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; public static final fun expressionInRing (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; - public static final fun expressionInSpace (Lspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; + public static final fun expressionInSpace (Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; } public class space/kscience/kmath/expressions/FunctionalExpressionExtendedField : space/kscience/kmath/expressions/FunctionalExpressionField, space/kscience/kmath/operations/ExtendedField { @@ -165,22 +165,8 @@ public class space/kscience/kmath/expressions/FunctionalExpressionField : space/ public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } -public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/kscience/kmath/expressions/FunctionalExpressionSpace, space/kscience/kmath/operations/Ring { - public fun (Lspace/kscience/kmath/operations/Ring;)V - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun getOne ()Ljava/lang/Object; - public fun getOne ()Lspace/kscience/kmath/expressions/Expression; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public final fun times (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public final fun times (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression; - public fun times (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; -} - -public class space/kscience/kmath/expressions/FunctionalExpressionSpace : space/kscience/kmath/expressions/FunctionalExpressionAlgebra, space/kscience/kmath/operations/Space { - public fun (Lspace/kscience/kmath/operations/Space;)V +public class space/kscience/kmath/expressions/FunctionalExpressionGroup : space/kscience/kmath/expressions/FunctionalExpressionAlgebra, space/kscience/kmath/operations/Group { + public fun (Lspace/kscience/kmath/operations/Group;)V public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; @@ -201,6 +187,20 @@ public class space/kscience/kmath/expressions/FunctionalExpressionSpace : space/ public fun unaryPlus (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; } +public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/kscience/kmath/expressions/FunctionalExpressionGroup, space/kscience/kmath/operations/Ring { + public fun (Lspace/kscience/kmath/operations/Ring;)V + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun getOne ()Ljava/lang/Object; + public fun getOne ()Lspace/kscience/kmath/expressions/Expression; + public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun multiply (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public final fun times (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; + public final fun times (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression; + public fun times (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; +} + public final class space/kscience/kmath/expressions/SimpleAutoDiffExpression : space/kscience/kmath/expressions/FirstDerivativeExpression { public fun (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)V public fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression; @@ -490,7 +490,7 @@ public final class space/kscience/kmath/linear/BufferMatrixContext : space/kscie public final class space/kscience/kmath/linear/BufferMatrixContext$Companion { } -public final class space/kscience/kmath/linear/BufferVectorSpace : space/kscience/kmath/linear/VectorSpace { +public final class space/kscience/kmath/linear/BufferVectorGroup : space/kscience/kmath/linear/VectorSpace { public fun (ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; @@ -625,7 +625,7 @@ public final class space/kscience/kmath/linear/MatrixBuilderKt { public static final fun row (Lspace/kscience/kmath/nd/Structure2D$Companion;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; } -public abstract interface class space/kscience/kmath/linear/MatrixContext : space/kscience/kmath/operations/SpaceOperations { +public abstract interface class space/kscience/kmath/linear/MatrixContext : space/kscience/kmath/operations/GroupOperations { public static final field Companion Lspace/kscience/kmath/linear/MatrixContext$Companion; public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; @@ -763,7 +763,7 @@ public final class space/kscience/kmath/linear/UnitFeature : space/kscience/kmat public static final field INSTANCE Lspace/kscience/kmath/linear/UnitFeature; } -public abstract interface class space/kscience/kmath/linear/VectorSpace : space/kscience/kmath/operations/Space { +public abstract interface class space/kscience/kmath/linear/VectorSpace : space/kscience/kmath/operations/Group { public static final field Companion Lspace/kscience/kmath/linear/VectorSpace$Companion; public abstract fun add (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public abstract fun getAlgebra ()Lspace/kscience/kmath/operations/Ring; @@ -775,9 +775,9 @@ public abstract interface class space/kscience/kmath/linear/VectorSpace : space/ } public final class space/kscience/kmath/linear/VectorSpace$Companion { - public final fun buffered (ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferVectorSpace; - public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/VectorSpace$Companion;ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/BufferVectorSpace; - public final fun real (I)Lspace/kscience/kmath/linear/BufferVectorSpace; + public final fun buffered (ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferVectorGroup; + public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/VectorSpace$Companion;ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/BufferVectorGroup; + public final fun real (I)Lspace/kscience/kmath/linear/BufferVectorGroup; } public final class space/kscience/kmath/linear/VectorSpace$DefaultImpls { @@ -820,9 +820,9 @@ public final class space/kscience/kmath/misc/CumulativeKt { public static final fun cumulative (Ljava/util/Iterator;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/util/Iterator; public static final fun cumulative (Ljava/util/List;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public static final fun cumulative (Lkotlin/sequences/Sequence;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Lkotlin/sequences/Sequence; - public static final fun cumulativeSum (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Space;)Ljava/lang/Iterable; - public static final fun cumulativeSum (Ljava/util/List;Lspace/kscience/kmath/operations/Space;)Ljava/util/List; - public static final fun cumulativeSum (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Space;)Lkotlin/sequences/Sequence; + public static final fun cumulativeSum (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Iterable; + public static final fun cumulativeSum (Ljava/util/List;Lspace/kscience/kmath/operations/Group;)Ljava/util/List; + public static final fun cumulativeSum (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Group;)Lkotlin/sequences/Sequence; public static final fun cumulativeSumOfDouble (Ljava/lang/Iterable;)Ljava/lang/Iterable; public static final fun cumulativeSumOfDouble (Ljava/util/List;)Ljava/util/List; public static final fun cumulativeSumOfDouble (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; @@ -860,9 +860,9 @@ public final class space/kscience/kmath/nd/BufferNDAlgebraKt { public static final fun field (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDField; public static final fun ndField (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun ndRing (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun ndSpace (Lspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun ndSpace (Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun ring (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDRing; - public static final fun space (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDSpace; + public static final fun space (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDGroup; } public class space/kscience/kmath/nd/BufferedNDField : space/kscience/kmath/nd/BufferedNDRing, space/kscience/kmath/nd/NDField { @@ -892,21 +892,8 @@ public class space/kscience/kmath/nd/BufferedNDField : space/kscience/kmath/nd/B public fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; } -public class space/kscience/kmath/nd/BufferedNDRing : space/kscience/kmath/nd/BufferedNDSpace, space/kscience/kmath/nd/NDRing { - public fun ([ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun getOne ()Ljava/lang/Object; - public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public fun times (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; -} - -public class space/kscience/kmath/nd/BufferedNDSpace : space/kscience/kmath/nd/BufferNDAlgebra, space/kscience/kmath/nd/NDSpace { - public fun ([ILspace/kscience/kmath/operations/Space;Lkotlin/jvm/functions/Function2;)V +public class space/kscience/kmath/nd/BufferedNDGroup : space/kscience/kmath/nd/BufferNDAlgebra, space/kscience/kmath/nd/NDGroup { + public fun ([ILspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;)V public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -919,7 +906,7 @@ public class space/kscience/kmath/nd/BufferedNDSpace : space/kscience/kmath/nd/B public fun getBuffer (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/structures/Buffer; public final fun getBufferFactory ()Lkotlin/jvm/functions/Function2; public synthetic fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; - public final fun getElementContext ()Lspace/kscience/kmath/operations/Space; + public final fun getElementContext ()Lspace/kscience/kmath/operations/Group; public final fun getShape ()[I public fun getStrides ()Lspace/kscience/kmath/nd/Strides; public synthetic fun getZero ()Ljava/lang/Object; @@ -948,6 +935,19 @@ public class space/kscience/kmath/nd/BufferedNDSpace : space/kscience/kmath/nd/B public fun unaryPlus (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; } +public class space/kscience/kmath/nd/BufferedNDRing : space/kscience/kmath/nd/BufferedNDGroup, space/kscience/kmath/nd/NDRing { + public fun ([ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun getOne ()Ljava/lang/Object; + public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun multiply (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; + public fun times (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; +} + public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath/nd/Strides { public static final field Companion Lspace/kscience/kmath/nd/DefaultStrides$Companion; public synthetic fun ([ILkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -1050,7 +1050,36 @@ public final class space/kscience/kmath/nd/NDField$DefaultImpls { public static fun unaryPlus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; } -public abstract interface class space/kscience/kmath/nd/NDRing : space/kscience/kmath/nd/NDSpace, space/kscience/kmath/operations/Ring { +public abstract interface class space/kscience/kmath/nd/NDGroup : space/kscience/kmath/nd/NDAlgebra, space/kscience/kmath/operations/Group { + public static final field Companion Lspace/kscience/kmath/nd/NDGroup$Companion; + public abstract fun add (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public abstract fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; + public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public abstract fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; +} + +public final class space/kscience/kmath/nd/NDGroup$Companion { +} + +public final class space/kscience/kmath/nd/NDGroup$DefaultImpls { + public static fun add (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public static fun binaryOperation (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public static fun bindSymbol (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure; + public static fun invoke (Lspace/kscience/kmath/nd/NDGroup;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public static fun minus (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public static fun minus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; + public static fun minus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public static fun plus (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public static fun plus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; + public static fun plus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public static fun unaryOperation (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public static fun unaryPlus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; +} + +public abstract interface class space/kscience/kmath/nd/NDRing : space/kscience/kmath/nd/NDGroup, space/kscience/kmath/operations/Ring { public static final field Companion Lspace/kscience/kmath/nd/NDRing$Companion; public abstract fun multiply (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; @@ -1081,35 +1110,6 @@ public final class space/kscience/kmath/nd/NDRing$DefaultImpls { public static fun unaryPlus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; } -public abstract interface class space/kscience/kmath/nd/NDSpace : space/kscience/kmath/nd/NDAlgebra, space/kscience/kmath/operations/Space { - public static final field Companion Lspace/kscience/kmath/nd/NDSpace$Companion; - public abstract fun add (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; -} - -public final class space/kscience/kmath/nd/NDSpace$Companion { -} - -public final class space/kscience/kmath/nd/NDSpace$DefaultImpls { - public static fun add (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun binaryOperation (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure; - public static fun invoke (Lspace/kscience/kmath/nd/NDSpace;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun minus (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun minus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public static fun minus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun plus (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun plus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public static fun plus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun unaryOperation (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/NDSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/nd/NDSpace;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; -} - public abstract interface class space/kscience/kmath/nd/NDStructure { public static final field Companion Lspace/kscience/kmath/nd/NDStructure$Companion; public abstract fun elements ()Lkotlin/sequences/Sequence; @@ -1333,17 +1333,17 @@ public final class space/kscience/kmath/operations/AlgebraElementsKt { } public final class space/kscience/kmath/operations/AlgebraExtensionsKt { - public static final fun abs (Lspace/kscience/kmath/operations/Space;Ljava/lang/Comparable;)Ljava/lang/Comparable; - public static final fun average (Lspace/kscience/kmath/operations/Space;Ljava/lang/Iterable;)Ljava/lang/Object; - public static final fun average (Lspace/kscience/kmath/operations/Space;Lkotlin/sequences/Sequence;)Ljava/lang/Object; - public static final fun averageWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Space;)Ljava/lang/Object; - public static final fun averageWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Space;)Ljava/lang/Object; + public static final fun abs (Lspace/kscience/kmath/operations/Group;Ljava/lang/Comparable;)Ljava/lang/Comparable; + public static final fun average (Lspace/kscience/kmath/operations/Group;Ljava/lang/Iterable;)Ljava/lang/Object; + public static final fun average (Lspace/kscience/kmath/operations/Group;Lkotlin/sequences/Sequence;)Ljava/lang/Object; + public static final fun averageWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object; + public static final fun averageWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object; public static final fun power (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;I)Ljava/lang/Object; public static final fun power (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;I)Ljava/lang/Object; - public static final fun sum (Lspace/kscience/kmath/operations/Space;Ljava/lang/Iterable;)Ljava/lang/Object; - public static final fun sum (Lspace/kscience/kmath/operations/Space;Lkotlin/sequences/Sequence;)Ljava/lang/Object; - public static final fun sumWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Space;)Ljava/lang/Object; - public static final fun sumWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Space;)Ljava/lang/Object; + public static final fun sum (Lspace/kscience/kmath/operations/Group;Ljava/lang/Iterable;)Ljava/lang/Object; + public static final fun sum (Lspace/kscience/kmath/operations/Group;Lkotlin/sequences/Sequence;)Ljava/lang/Object; + public static final fun sumWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object; + public static final fun sumWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object; } public final class space/kscience/kmath/operations/AlgebraKt { @@ -1735,6 +1735,50 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; } +public abstract interface class space/kscience/kmath/operations/Group : space/kscience/kmath/operations/GroupOperations { + public abstract fun getZero ()Ljava/lang/Object; +} + +public final class space/kscience/kmath/operations/Group$DefaultImpls { + public static fun binaryOperation (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public static fun bindSymbol (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Ljava/lang/Object; + public static fun minus (Lspace/kscience/kmath/operations/Group;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun plus (Lspace/kscience/kmath/operations/Group;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun unaryOperation (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public static fun unaryPlus (Lspace/kscience/kmath/operations/Group;Ljava/lang/Object;)Ljava/lang/Object; +} + +public abstract interface class space/kscience/kmath/operations/GroupOperations : space/kscience/kmath/operations/Algebra { + public static final field Companion Lspace/kscience/kmath/operations/GroupOperations$Companion; + public static final field MINUS_OPERATION Ljava/lang/String; + public static final field PLUS_OPERATION Ljava/lang/String; + public abstract fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public abstract fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public abstract fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/operations/GroupOperations$Companion { + public static final field MINUS_OPERATION Ljava/lang/String; + public static final field PLUS_OPERATION Ljava/lang/String; +} + +public final class space/kscience/kmath/operations/GroupOperations$DefaultImpls { + public static fun binaryOperation (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public static fun bindSymbol (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Ljava/lang/Object; + public static fun minus (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun plus (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun unaryOperation (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public static fun unaryPlus (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/Object;)Ljava/lang/Object; +} + public final class space/kscience/kmath/operations/IntRing : space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring { public static final field INSTANCE Lspace/kscience/kmath/operations/IntRing; public fun add (II)Ljava/lang/Integer; @@ -2078,7 +2122,7 @@ public final class space/kscience/kmath/operations/RealField : space/kscience/km public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; } -public abstract interface class space/kscience/kmath/operations/Ring : space/kscience/kmath/operations/RingOperations, space/kscience/kmath/operations/Space { +public abstract interface class space/kscience/kmath/operations/Ring : space/kscience/kmath/operations/Group, space/kscience/kmath/operations/RingOperations { public abstract fun getOne ()Ljava/lang/Object; } @@ -2094,7 +2138,7 @@ public final class space/kscience/kmath/operations/Ring$DefaultImpls { public static fun unaryPlus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;)Ljava/lang/Object; } -public abstract interface class space/kscience/kmath/operations/RingOperations : space/kscience/kmath/operations/SpaceOperations { +public abstract interface class space/kscience/kmath/operations/RingOperations : space/kscience/kmath/operations/GroupOperations { public static final field Companion Lspace/kscience/kmath/operations/RingOperations$Companion; public static final field TIMES_OPERATION Ljava/lang/String; public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; @@ -2176,50 +2220,6 @@ public final class space/kscience/kmath/operations/ShortRing : space/kscience/km public fun unaryPlus (S)Ljava/lang/Short; } -public abstract interface class space/kscience/kmath/operations/Space : space/kscience/kmath/operations/SpaceOperations { - public abstract fun getZero ()Ljava/lang/Object; -} - -public final class space/kscience/kmath/operations/Space$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;)Ljava/lang/Object; - public static fun minus (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Space;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/operations/Space;Ljava/lang/Object;)Ljava/lang/Object; -} - -public abstract interface class space/kscience/kmath/operations/SpaceOperations : space/kscience/kmath/operations/Algebra { - public static final field Companion Lspace/kscience/kmath/operations/SpaceOperations$Companion; - public static final field MINUS_OPERATION Ljava/lang/String; - public static final field PLUS_OPERATION Ljava/lang/String; - public abstract fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public abstract fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public abstract fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class space/kscience/kmath/operations/SpaceOperations$Companion { - public static final field MINUS_OPERATION Ljava/lang/String; - public static final field PLUS_OPERATION Ljava/lang/String; -} - -public final class space/kscience/kmath/operations/SpaceOperations$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun minus (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/operations/SpaceOperations;Ljava/lang/Object;)Ljava/lang/Object; -} - public abstract interface class space/kscience/kmath/operations/TrigonometricOperations : space/kscience/kmath/operations/Algebra { public static final field ACOS_OPERATION Ljava/lang/String; public static final field ASIN_OPERATION Ljava/lang/String; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index 3c23d0ecf..880f13a3e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -41,21 +41,21 @@ public abstract class FunctionalExpressionAlgebra>( } /** - * A context class for [Expression] construction for [Space] algebras. + * A context class for [Expression] construction for [Group] algebras. */ -public open class FunctionalExpressionSpace>( +public open class FunctionalExpressionGroup>( algebra: A, -) : FunctionalExpressionAlgebra(algebra), Space> { +) : FunctionalExpressionAlgebra(algebra), Group> { public override val zero: Expression get() = const(algebra.zero) override fun Expression.unaryMinus(): Expression = - unaryOperation(SpaceOperations.MINUS_OPERATION, this) + unaryOperation(GroupOperations.MINUS_OPERATION, this) /** * Builds an Expression of addition of two another expressions. */ public override fun add(a: Expression, b: Expression): Expression = - binaryOperation(SpaceOperations.PLUS_OPERATION, a, b) + binaryOperation(GroupOperations.PLUS_OPERATION, a, b) // /** // * Builds an Expression of multiplication of expression by number. @@ -79,7 +79,7 @@ public open class FunctionalExpressionSpace>( public open class FunctionalExpressionRing>( algebra: A, -) : FunctionalExpressionSpace(algebra), Ring> { +) : FunctionalExpressionGroup(algebra), Ring> { public override val one: Expression get() = const(algebra.one) /** @@ -92,10 +92,10 @@ public open class FunctionalExpressionRing>( public operator fun T.times(arg: Expression): Expression = arg * this public override fun unaryOperationFunction(operation: String): (arg: Expression) -> Expression = - super.unaryOperationFunction(operation) + super.unaryOperationFunction(operation) public override fun binaryOperationFunction(operation: String): (left: Expression, right: Expression) -> Expression = - super.binaryOperationFunction(operation) + super.binaryOperationFunction(operation) } public open class FunctionalExpressionField>( @@ -159,8 +159,8 @@ public open class FunctionalExpressionExtendedField>( super.binaryOperationFunction(operation) } -public inline fun > A.expressionInSpace(block: FunctionalExpressionSpace.() -> Expression): Expression = - FunctionalExpressionSpace(this).block() +public inline fun > A.expressionInSpace(block: FunctionalExpressionGroup.() -> Expression): Expression = + FunctionalExpressionGroup(this).block() public inline fun > A.expressionInRing(block: FunctionalExpressionRing.() -> Expression): Expression = FunctionalExpressionRing(this).block() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt index 0ef6803d6..fbf080032 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt @@ -2,18 +2,18 @@ package space.kscience.kmath.expressions import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.Space import kotlin.contracts.InvocationKind import kotlin.contracts.contract /** - * Creates a functional expression with this [Space]. + * Creates a functional expression with this [Group]. */ -public inline fun Space.spaceExpression(block: FunctionalExpressionSpace>.() -> Expression): Expression { +public inline fun Group.spaceExpression(block: FunctionalExpressionGroup>.() -> Expression): Expression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return FunctionalExpressionSpace(this).block() + return FunctionalExpressionGroup(this).block() } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt index 639d77e85..b8937885a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt @@ -13,7 +13,7 @@ import kotlin.reflect.KClass * @param T the type of items in the matrices. * @param M the type of operated matrices. */ -public interface MatrixContext> : SpaceOperations> { +public interface MatrixContext> : GroupOperations> { /** * Produces a matrix with this context and given dimensions. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt index fd3144d24..570c87b81 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.linear +import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory @@ -11,7 +11,7 @@ import space.kscience.kmath.structures.BufferFactory * A linear space for vectors. * Could be used on any point-like structure */ -public interface VectorSpace> : Space> { +public interface VectorSpace> : Group> { public val size: Int public val algebra: A override val zero: Point get() = produce { algebra.zero } @@ -27,13 +27,13 @@ public interface VectorSpace> : Space> { //TODO add basis public companion object { - private val realSpaceCache: MutableMap> = hashMapOf() + private val realSpaceCache: MutableMap> = hashMapOf() /** * Non-boxing double vector space */ - public fun real(size: Int): BufferVectorSpace = realSpaceCache.getOrPut(size) { - BufferVectorSpace( + public fun real(size: Int): BufferVectorGroup = realSpaceCache.getOrPut(size) { + BufferVectorGroup( size, RealField, Buffer.Companion::auto @@ -47,7 +47,7 @@ public interface VectorSpace> : Space> { size: Int, space: A, bufferFactory: BufferFactory = Buffer.Companion::boxing, - ): BufferVectorSpace = BufferVectorSpace(size, space, bufferFactory) + ): BufferVectorGroup = BufferVectorGroup(size, space, bufferFactory) /** * Automatic buffered vector, unboxed if it is possible @@ -58,7 +58,7 @@ public interface VectorSpace> : Space> { } -public class BufferVectorSpace>( +public class BufferVectorGroup>( override val size: Int, override val algebra: A, public val bufferFactory: BufferFactory, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt index 380723095..b50e095cf 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.misc -import space.kscience.kmath.operations.Space +import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.invoke import kotlin.jvm.JvmName @@ -37,7 +37,7 @@ public fun List.cumulative(initial: R, operation: (R, T) -> R): List Iterable.cumulativeSum(space: Space): Iterable = +public fun Iterable.cumulativeSum(space: Group): Iterable = space { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") @@ -49,7 +49,7 @@ public fun Iterable.cumulativeSum(): Iterable = cumulative(0) { elemen @JvmName("cumulativeSumOfLong") public fun Iterable.cumulativeSum(): Iterable = cumulative(0L) { element, sum -> sum + element } -public fun Sequence.cumulativeSum(space: Space): Sequence = +public fun Sequence.cumulativeSum(space: Group): Sequence = space { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") @@ -61,7 +61,7 @@ public fun Sequence.cumulativeSum(): Sequence = cumulative(0) { elemen @JvmName("cumulativeSumOfLong") public fun Sequence.cumulativeSum(): Sequence = cumulative(0L) { element, sum -> sum + element } -public fun List.cumulativeSum(space: Space): List = +public fun List.cumulativeSum(space: Group): List = space { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt index ff9c911ac..58d1ea7b1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt @@ -52,11 +52,11 @@ public interface BufferNDAlgebra> : NDAlgebra { } } -public open class BufferedNDSpace>( +public open class BufferedNDGroup>( final override val shape: IntArray, final override val elementContext: A, final override val bufferFactory: BufferFactory, -) : NDSpace, BufferNDAlgebra { +) : NDGroup, BufferNDAlgebra { override val strides: Strides = DefaultStrides(shape) override val zero: NDBuffer by lazy { produce { zero } } override fun NDStructure.unaryMinus(): NDStructure = produce { -get(it) } @@ -66,7 +66,7 @@ public open class BufferedNDRing>( shape: IntArray, elementContext: R, bufferFactory: BufferFactory, -) : BufferedNDSpace(shape, elementContext, bufferFactory), NDRing { +) : BufferedNDGroup(shape, elementContext, bufferFactory), NDRing { override val one: NDBuffer by lazy { produce { one } } } @@ -80,16 +80,16 @@ public open class BufferedNDField>( } // space factories -public fun > NDAlgebra.Companion.space( +public fun > NDAlgebra.Companion.space( space: A, bufferFactory: BufferFactory, vararg shape: Int, -): BufferedNDSpace = BufferedNDSpace(shape, space, bufferFactory) +): BufferedNDGroup = BufferedNDGroup(shape, space, bufferFactory) -public inline fun , R> A.ndSpace( +public inline fun , R> A.ndSpace( noinline bufferFactory: BufferFactory, vararg shape: Int, - action: BufferedNDSpace.() -> R, + action: BufferedNDGroup.() -> R, ): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } return NDAlgebra.space(this, bufferFactory, *shape).run(action) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt index 6b6e887dc..e3ffae74b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt @@ -54,7 +54,7 @@ public interface NDAlgebra> { * Element-wise invocation of function working on [T] on a [NDStructure]. */ public operator fun Function1.invoke(structure: NDStructure): NDStructure = - structure.map() { value -> this@invoke(value) } + structure.map { value -> this@invoke(value) } public companion object } @@ -89,7 +89,7 @@ internal fun > NDAlgebra.checkShape(element: NDStructure< * @param N the type of ND structure. * @param S the type of space of structure elements. */ -public interface NDSpace> : Space>, NDAlgebra { +public interface NDGroup> : Group>, NDAlgebra { /** * Element-wise addition. * @@ -127,7 +127,7 @@ public interface NDSpace> : Space>, NDAlgebra.minus(arg: T): NDStructure = this.map() { value -> add(arg, -value) } + public operator fun NDStructure.minus(arg: T): NDStructure = this.map { value -> add(arg, -value) } /** * Adds an element to ND structure of it. @@ -136,7 +136,7 @@ public interface NDSpace> : Space>, NDAlgebra): NDStructure = arg.map() { value -> add(this@plus, value) } + public operator fun T.plus(arg: NDStructure): NDStructure = arg.map { value -> add(this@plus, value) } /** * Subtracts an ND structure from an element of it. @@ -145,7 +145,7 @@ public interface NDSpace> : Space>, NDAlgebra): NDStructure = arg.map() { value -> add(-this@minus, value) } + public operator fun T.minus(arg: NDStructure): NDStructure = arg.map { value -> add(-this@minus, value) } public companion object } @@ -157,7 +157,7 @@ public interface NDSpace> : Space>, NDAlgebra> : Ring>, NDSpace { +public interface NDRing> : Ring>, NDGroup { /** * Element-wise multiplication. * @@ -177,7 +177,7 @@ public interface NDRing> : Ring>, NDSpace { * @param arg the multiplier. * @return the product. */ - public operator fun NDStructure.times(arg: T): NDStructure = this.map() { value -> multiply(arg, value) } + public operator fun NDStructure.times(arg: T): NDStructure = this.map { value -> multiply(arg, value) } /** * Multiplies an element by a ND structure of it. @@ -186,7 +186,7 @@ public interface NDRing> : Ring>, NDSpace { * @param arg the multiplier. * @return the product. */ - public operator fun T.times(arg: NDStructure): NDStructure = arg.map() { value -> multiply(this@times, value) } + public operator fun T.times(arg: NDStructure): NDStructure = arg.map { value -> multiply(this@times, value) } public companion object } @@ -217,7 +217,7 @@ public interface NDField> : Field>, NDRing, * @param arg the divisor. * @return the quotient. */ - public operator fun NDStructure.div(arg: T): NDStructure = this.map() { value -> divide(arg, value) } + public operator fun NDStructure.div(arg: T): NDStructure = this.map { value -> divide(arg, value) } /** * Divides an element by an ND structure of it. @@ -226,7 +226,7 @@ public interface NDField> : Field>, NDRing, * @param arg the divisor. * @return the quotient. */ - public operator fun T.div(arg: NDStructure): NDStructure = arg.map() { divide(it, this@div) } + public operator fun T.div(arg: NDStructure): NDStructure = arg.map { divide(it, this@div) } // @ThreadLocal // public companion object { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 2163f61b2..0198700f2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -105,7 +105,7 @@ public inline operator fun , R> A.invoke(block: A.() -> R): R = r * * @param T the type of element of this semispace. */ -public interface SpaceOperations : Algebra { +public interface GroupOperations : Algebra { /** * Addition of two elements. * @@ -177,12 +177,11 @@ public interface SpaceOperations : Algebra { } /** - * Represents linear space with neutral element, i.e. algebraic structure with associative, binary operation [add] and - * scalar multiplication [multiply]. + * Represents linear space with neutral element, i.e. algebraic structure with associative, binary operation [add]. * * @param T the type of element of this semispace. */ -public interface Space : SpaceOperations { +public interface Group : GroupOperations { /** * The neutral element of addition. */ @@ -195,7 +194,7 @@ public interface Space : SpaceOperations { * * @param T the type of element of this semiring. */ -public interface RingOperations : SpaceOperations { +public interface RingOperations : GroupOperations { /** * Multiplies two elements. * @@ -231,7 +230,7 @@ public interface RingOperations : SpaceOperations { * * @param T the type of element of this ring. */ -public interface Ring : Space, RingOperations { +public interface Ring : Group, RingOperations { /** * neutral operation for multiplication */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt index 1fb4f6750..3e42ac094 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt @@ -49,7 +49,7 @@ public operator fun , S : NumbersAddOperations> T.mi * @param b the augend. * @return the sum. */ -public operator fun , S : Space> T.plus(b: T): T = +public operator fun , S : Group> T.plus(b: T): T = context.add(this, b) ///** @@ -80,14 +80,14 @@ public operator fun , F : Field> T.div(b: T): T = /** - * The element of [Space]. + * The element of [Group]. * * @param T the type of space operation results. * @param I self type of the element. Needed for static type checking. * @param S the type of space. */ @UnstableKMathAPI -public interface SpaceElement, S : Space> : AlgebraElement +public interface SpaceElement, S : Group> : AlgebraElement /** * The element of [Ring]. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt index 5f6ec869a..bd5f5951f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt @@ -127,7 +127,7 @@ public interface ScaleOperations : Algebra { * TODO to be removed and replaced by extensions after multiple receivers are there */ @UnstableKMathAPI -public interface NumbersAddOperations : Space, NumericAlgebra { +public interface NumbersAddOperations : Group, NumericAlgebra { /** * Addition of element and scalar. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 66b16b6f6..52a0dec6f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -1,49 +1,49 @@ package space.kscience.kmath.operations /** - * Returns the sum of all elements in the iterable in this [Space]. + * Returns the sum of all elements in the iterable in this [Group]. * * @receiver the algebra that provides addition. * @param data the iterable to sum up. * @return the sum. */ -public fun Space.sum(data: Iterable): T = data.fold(zero) { left, right -> add(left, right) } +public fun Group.sum(data: Iterable): T = data.fold(zero) { left, right -> add(left, right) } /** - * Returns the sum of all elements in the sequence in this [Space]. + * Returns the sum of all elements in the sequence in this [Group]. * * @receiver the algebra that provides addition. * @param data the sequence to sum up. * @return the sum. */ -public fun Space.sum(data: Sequence): T = data.fold(zero) { left, right -> add(left, right) } +public fun Group.sum(data: Sequence): T = data.fold(zero) { left, right -> add(left, right) } /** - * Returns an average value of elements in the iterable in this [Space]. + * Returns an average value of elements in the iterable in this [Group]. * * @receiver the algebra that provides addition and division. * @param data the iterable to find average. * @return the average value. * @author Iaroslav Postovalov */ -public fun S.average(data: Iterable): T where S : Space, S : ScaleOperations = +public fun S.average(data: Iterable): T where S : Group, S : ScaleOperations = sum(data) / data.count() /** - * Returns an average value of elements in the sequence in this [Space]. + * Returns an average value of elements in the sequence in this [Group]. * * @receiver the algebra that provides addition and division. * @param data the sequence to find average. * @return the average value. * @author Iaroslav Postovalov */ -public fun S.average(data: Sequence): T where S : Space, S : ScaleOperations = +public fun S.average(data: Sequence): T where S : Group, S : ScaleOperations = sum(data) / data.count() /** * Absolute of the comparable [value] */ -public fun > Space.abs(value: T): T = if (value > zero) value else -value +public fun > Group.abs(value: T): T = if (value > zero) value else -value /** * Returns the sum of all elements in the iterable in provided space. @@ -52,7 +52,7 @@ public fun > Space.abs(value: T): T = if (value > zero) val * @param space the algebra that provides addition. * @return the sum. */ -public fun Iterable.sumWith(space: Space): T = space.sum(this) +public fun Iterable.sumWith(space: Group): T = space.sum(this) /** * Returns the sum of all elements in the sequence in provided space. @@ -61,28 +61,28 @@ public fun Iterable.sumWith(space: Space): T = space.sum(this) * @param space the algebra that provides addition. * @return the sum. */ -public fun Sequence.sumWith(space: Space): T = space.sum(this) +public fun Sequence.sumWith(space: Group): T = space.sum(this) /** - * Returns an average value of elements in the iterable in this [Space]. + * Returns an average value of elements in the iterable in this [Group]. * * @receiver the iterable to find average. * @param space the algebra that provides addition and division. * @return the average value. * @author Iaroslav Postovalov */ -public fun Iterable.averageWith(space: S): T where S : Space, S : ScaleOperations = +public fun Iterable.averageWith(space: S): T where S : Group, S : ScaleOperations = space.average(this) /** - * Returns an average value of elements in the sequence in this [Space]. + * Returns an average value of elements in the sequence in this [Group]. * * @receiver the sequence to find average. * @param space the algebra that provides addition and division. * @return the average value. * @author Iaroslav Postovalov */ -public fun Sequence.averageWith(space: S): T where S : Space, S : ScaleOperations = +public fun Sequence.averageWith(space: S): T where S : Group, S : ScaleOperations = space.average(this) //TODO optimized power operation diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt index 6ea75156b..a9cd4454c 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.testutils +import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.invoke import kotlin.test.assertEquals import kotlin.test.assertNotEquals @@ -12,7 +12,7 @@ internal open class SpaceVerifier( val b: T, val c: T, val x: Number, -) : AlgebraicVerifier> where S : Space, S : ScaleOperations { +) : AlgebraicVerifier> where S : Group, S : ScaleOperations { override fun verify() { algebra { assertEquals(a + b + c, a + (b + c), "Addition in $algebra is not associative.") diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt index eff813bee..81b4327fc 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt @@ -5,16 +5,16 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.runningReduce import kotlinx.coroutines.flow.scan +import space.kscience.kmath.operations.Group +import space.kscience.kmath.operations.GroupOperations import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.Space -import space.kscience.kmath.operations.SpaceOperations import space.kscience.kmath.operations.invoke -public fun Flow.cumulativeSum(space: SpaceOperations): Flow = - space { runningReduce { sum, element -> sum + element } } +public fun Flow.cumulativeSum(group: GroupOperations): Flow = + group { runningReduce { sum, element -> sum + element } } @ExperimentalCoroutinesApi -public fun Flow.mean(algebra: S): Flow where S : Space, S : ScaleOperations = algebra { +public fun Flow.mean(algebra: S): Flow where S : Group, S : ScaleOperations = algebra { data class Accumulator(var sum: T, var num: Int) scan(Accumulator(zero, 0)) { sum, element -> diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 9141fa7b9..049909fe1 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.functions +import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.invoke import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -44,7 +44,7 @@ public fun > Polynomial.asFunction(ring: C): (T) -> T = */ public class PolynomialSpace( private val ring: C, -) : Space>, ScaleOperations> where C : Ring, C : ScaleOperations { +) : Group>, ScaleOperations> where C : Ring, C : ScaleOperations { public override val zero: Polynomial = Polynomial(emptyList()) override fun Polynomial.unaryMinus(): Polynomial = with(ring) { diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt index 392156e9f..808bd692f 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt @@ -1,10 +1,10 @@ package space.kscience.kmath.geometry -import space.kscience.kmath.operations.Space +import space.kscience.kmath.operations.Group public interface Vector -public interface GeometrySpace : Space { +public interface GeometrySpace : Group { /** * L2 distance */ diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt index 55e8c0631..d5f3965d9 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt @@ -2,8 +2,8 @@ package space.kscience.kmath.histogram import kotlinx.atomicfu.atomic import kotlinx.atomicfu.getAndUpdate +import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.RealField -import space.kscience.kmath.operations.Space /** * Common representation for atomic counters @@ -36,7 +36,7 @@ public class LongCounter : Counter { override val value: Long get() = innerValue.value } -public class ObjectCounter(public val space: Space) : Counter { +public class ObjectCounter(public val space: Group) : Counter { private val innerValue = atomic(space.zero) override fun add(delta: T) { diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt index b82644481..19128b2ac 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt @@ -6,8 +6,8 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.NDField import space.kscience.kmath.nd.NDStructure import space.kscience.kmath.nd.Strides +import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.SpaceElement import space.kscience.kmath.operations.invoke @@ -43,7 +43,7 @@ public class IndexedHistogram, V : Any>( * A space for producing histograms with values in a NDStructure */ public interface IndexedHistogramSpace, V : Any> - : Space>, ScaleOperations> { + : Group>, ScaleOperations> { //public val valueSpace: Space public val strides: Strides public val histogramValueSpace: NDField //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape), diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt index 85e82f515..b2071fa02 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt @@ -2,8 +2,8 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.UnivariateDomain import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.Space import space.kscience.kmath.structures.Buffer import java.util.* import kotlin.math.abs @@ -37,7 +37,7 @@ public class TreeHistogram( @UnstableKMathAPI public class TreeHistogramSpace( public val binFactory: (Double) -> UnivariateDomain, -) : Space, ScaleOperations { +) : Group, ScaleOperations { private class BinCounter(val domain: UnivariateDomain, val counter: Counter = Counter.real()) : ClosedFloatingPointRange by domain.range diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt index 96e3d41ae..03bd096d9 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.UnivariateDomain import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Space +import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.SpaceElement import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asSequence @@ -30,7 +30,7 @@ public class UnivariateBin( @OptIn(UnstableKMathAPI::class) public interface UnivariateHistogram : Histogram, - SpaceElement> { + SpaceElement> { public operator fun get(value: Double): UnivariateBin? public override operator fun get(point: Buffer): UnivariateBin? = get(point[0]) diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt index 6ca6bc113..82b801f91 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -102,8 +102,8 @@ public fun > MST.toSFun(): SFun = when (this) { is MST.Symbolic -> toSVar() is MST.Unary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> +value.toSFun() - SpaceOperations.MINUS_OPERATION -> -value.toSFun() + GroupOperations.PLUS_OPERATION -> +value.toSFun() + GroupOperations.MINUS_OPERATION -> -value.toSFun() TrigonometricOperations.SIN_OPERATION -> sin(value.toSFun()) TrigonometricOperations.COS_OPERATION -> cos(value.toSFun()) TrigonometricOperations.TAN_OPERATION -> tan(value.toSFun()) @@ -114,8 +114,8 @@ public fun > MST.toSFun(): SFun = when (this) { } is MST.Binary -> when (operation) { - SpaceOperations.PLUS_OPERATION -> left.toSFun() + right.toSFun() - SpaceOperations.MINUS_OPERATION -> left.toSFun() - right.toSFun() + GroupOperations.PLUS_OPERATION -> left.toSFun() + right.toSFun() + GroupOperations.MINUS_OPERATION -> left.toSFun() - right.toSFun() RingOperations.TIMES_OPERATION -> left.toSFun() * right.toSFun() FieldOperations.DIV_OPERATION -> left.toSFun() / right.toSFun() PowerOperations.POW_OPERATION -> left.toSFun() pow (right as MST.Numeric).toSConst() diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index dea74abdc..d8ce1052a 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -70,12 +70,12 @@ public interface Nd4jArrayAlgebra> : NDAlgebra { } /** - * Represents [NDSpace] over [Nd4jArrayStructure]. + * Represents [NDGroup] over [Nd4jArrayStructure]. * * @param T the type of the element contained in ND structure. * @param S the type of space of structure elements. */ -public interface Nd4jArraySpace> : NDSpace, Nd4jArrayAlgebra { +public interface Nd4JArrayGroup> : NDGroup, Nd4jArrayAlgebra { public override val zero: Nd4jArrayStructure get() = Nd4j.zeros(*shape).wrap() @@ -100,7 +100,7 @@ public interface Nd4jArraySpace> : NDSpace, Nd4jArrayAlgeb * @param R the type of ring of structure elements. */ @OptIn(UnstableKMathAPI::class) -public interface Nd4jArrayRing> : NDRing, Nd4jArraySpace { +public interface Nd4jArrayRing> : NDRing, Nd4JArrayGroup { public override val one: Nd4jArrayStructure get() = Nd4j.ones(*shape).wrap() diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt index ca2fd58cc..c5ec99dae 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt @@ -4,8 +4,8 @@ import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.ConstantChain import space.kscience.kmath.chains.map import space.kscience.kmath.chains.zip +import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.Space import space.kscience.kmath.operations.invoke public class BasicSampler(public val chainBuilder: (RandomGenerator) -> Chain) : Sampler { @@ -19,8 +19,8 @@ public class ConstantSampler(public val value: T) : Sampler { /** * A space for samplers. Allows to perform simple operations on distributions */ -public class SamplerSpace(public val algebra: S) : Space>, - ScaleOperations> where S : Space, S : ScaleOperations { +public class SamplerSpace(public val algebra: S) : Group>, + ScaleOperations> where S : Group, S : ScaleOperations { public override val zero: Sampler = ConstantSampler(algebra.zero) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt index 4a3103d1b..a9f7cd3e4 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt @@ -66,7 +66,7 @@ public fun ComposableStatistic.flow( * Arithmetic mean */ public class Mean( - private val space: Space, + private val space: Group, private val division: (sum: T, count: Int) -> T, ) : ComposableStatistic, T> { public override suspend fun computeIntermediate(data: Buffer): Pair = From fd51564628da781426226582f3c315d116106667 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 11 Mar 2021 10:18:59 +0300 Subject: [PATCH 043/393] Return field get access in algebras --- .../kotlin/space/kscience/kmath/ast/MstAlgebra.kt | 6 +++--- .../kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt index a65027147..16fdfbeac 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt @@ -50,7 +50,7 @@ public object MstGroup : Group, NumericAlgebra, ScaleOperations { */ @OptIn(UnstableKMathAPI::class) public object MstRing : Ring, NumbersAddOperations, ScaleOperations { - public override val zero: MST.Numeric = MstGroup.zero + public override val zero: MST.Numeric get() = MstGroup.zero public override val one: MST.Numeric = number(1.0) public override fun number(value: Number): MST.Numeric = MstGroup.number(value) @@ -109,8 +109,8 @@ public object MstField : Field, NumbersAddOperations, ScaleOperations< * [ExtendedField] over [MST] nodes. */ public object MstExtendedField : ExtendedField, NumericAlgebra { - public override val zero: MST.Numeric = MstField.zero - public override val one: MST.Numeric = MstField.one + public override val zero: MST.Numeric get() = MstField.zero + public override val one: MST.Numeric get() = MstField.one public override fun bindSymbol(value: String): MST.Symbolic = MstField.bindSymbol(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value) diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt index f5697cea2..d791ed675 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt @@ -40,11 +40,9 @@ public class ViktorNDField(public override val shape: IntArray) : NDField produce { this@f64Buffer[it] }.f64Buffer } - public override val zero: ViktorNDStructure - get() = F64Array.full(init = 0.0, shape = shape).asStructure() + public override val zero: ViktorNDStructure by lazy { F64Array.full(init = 0.0, shape = shape).asStructure() } - public override val one: ViktorNDStructure - get() = F64Array.full(init = 1.0, shape = shape).asStructure() + public override val one: ViktorNDStructure by lazy { F64Array.full(init = 1.0, shape = shape).asStructure() } private val strides: Strides = DefaultStrides(shape) From 803f298d8b27ecd0732bed869a29fd1ce8747ca0 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 11 Mar 2021 11:28:10 +0300 Subject: [PATCH 044/393] Make vector spaces great again --- CHANGELOG.md | 1 + .../space/kscience/kmath/ast/MstExpression.kt | 6 +-- .../TestESTreeConsistencyWithInterpreter.kt | 4 +- .../estree/TestESTreeOperationsSupport.kt | 6 +-- .../asm/TestAsmConsistencyWithInterpreter.kt | 4 +- .../kmath/asm/TestAsmOperationsSupport.kt | 6 +-- .../kscience/kmath/commons/linear/CMMatrix.kt | 3 ++ kmath-core/api/kmath-core.api | 48 ++++++++++++++----- .../kscience/kmath/linear/BufferMatrix.kt | 14 ++++-- .../kscience/kmath/linear/MatrixContext.kt | 18 +++---- .../kscience/kmath/linear/MatrixWrapper.kt | 31 +++++++----- .../kscience/kmath/linear/VectorSpace.kt | 27 ++++++----- .../kscience/kmath/geometry/GeometrySpace.kt | 3 +- 13 files changed, 109 insertions(+), 62 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a172eb69a..05c956de3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Changed - Exponential operations merged with hyperbolic functions - Space is replaced by Group. Space is reserved for vector spaces. +- VectorSpace is now a vector space ### Deprecated diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt index 3a598fb8c..63dfb38f7 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt @@ -58,7 +58,7 @@ public inline fun , E : Algebra> A.mst( * * @author Alexander Nozik */ -public inline fun > A.mstInSpace(block: MstGroup.() -> MST): MstExpression { +public inline fun > A.mstInGroup(block: MstGroup.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return MstExpression(this, MstGroup.block()) } @@ -98,9 +98,9 @@ public inline fun > A.mstInExtendedField(b * * @author Alexander Nozik */ -public inline fun > FunctionalExpressionGroup.mstInSpace(block: MstGroup.() -> MST): MstExpression { +public inline fun > FunctionalExpressionGroup.mstInGroup(block: MstGroup.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return algebra.mstInSpace(block) + return algebra.mstInGroup(block) } /** diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt index 34e9dd945..bb34254b1 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt @@ -12,7 +12,7 @@ import kotlin.test.assertEquals internal class TestESTreeConsistencyWithInterpreter { @Test fun mstSpace() { - val res1 = MstGroup.mstInSpace { + val res1 = MstGroup.mstInGroup { binaryOperationFunction("+")( unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (scale( @@ -25,7 +25,7 @@ internal class TestESTreeConsistencyWithInterpreter { ) + bindSymbol("x") + zero }("x" to MST.Numeric(2)) - val res2 = MstGroup.mstInSpace { + val res2 = MstGroup.mstInGroup { binaryOperationFunction("+")( unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (scale( diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt index 6e2f85327..27bf2f167 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.estree import space.kscience.kmath.ast.mstInExtendedField import space.kscience.kmath.ast.mstInField -import space.kscience.kmath.ast.mstInSpace +import space.kscience.kmath.ast.mstInGroup import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.RealField import kotlin.random.Random @@ -12,14 +12,14 @@ import kotlin.test.assertEquals internal class TestESTreeOperationsSupport { @Test fun testUnaryOperationInvocation() { - val expression = RealField.mstInSpace { -bindSymbol("x") }.compile() + val expression = RealField.mstInGroup { -bindSymbol("x") }.compile() val res = expression("x" to 2.0) assertEquals(-2.0, res) } @Test fun testBinaryOperationInvocation() { - val expression = RealField.mstInSpace { -bindSymbol("x") + number(1.0) }.compile() + val expression = RealField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile() val res = expression("x" to 2.0) assertEquals(-1.0, res) } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt index 4be2ee331..7cc1497d0 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt @@ -12,7 +12,7 @@ import kotlin.test.assertEquals internal class TestAsmConsistencyWithInterpreter { @Test fun mstSpace() { - val res1 = MstGroup.mstInSpace { + val res1 = MstGroup.mstInGroup { binaryOperationFunction("+")( unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (scale( @@ -25,7 +25,7 @@ internal class TestAsmConsistencyWithInterpreter { ) + bindSymbol("x") + zero }("x" to MST.Numeric(2)) - val res2 = MstGroup.mstInSpace { + val res2 = MstGroup.mstInGroup { binaryOperationFunction("+")( unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (scale( diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt index e3adc4629..e99075f07 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.asm import space.kscience.kmath.ast.mstInExtendedField import space.kscience.kmath.ast.mstInField -import space.kscience.kmath.ast.mstInSpace +import space.kscience.kmath.ast.mstInGroup import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.RealField import kotlin.random.Random @@ -12,14 +12,14 @@ import kotlin.test.assertEquals internal class TestAsmOperationsSupport { @Test fun testUnaryOperationInvocation() { - val expression = RealField.mstInSpace { -bindSymbol("x") }.compile() + val expression = RealField.mstInGroup { -bindSymbol("x") }.compile() val res = expression("x" to 2.0) assertEquals(-2.0, res) } @Test fun testBinaryOperationInvocation() { - val expression = RealField.mstInSpace { -bindSymbol("x") + number(1.0) }.compile() + val expression = RealField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile() val res = expression("x" to 2.0) assertEquals(-1.0, res) } diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index 537da5947..393b28973 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -86,6 +86,9 @@ public object CMMatrixContext : MatrixContext { } } + override fun scale(a: Matrix, value: Double): Matrix = a.toCM().times(value) + + public override fun Matrix.dot(other: Matrix): CMMatrix = CMMatrix(toCM().origin.multiply(other.toCM().origin)) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index eae91c985..8b30e4c05 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -460,6 +460,8 @@ public final class space/kscience/kmath/linear/BufferMatrixContext : space/kscie public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun div (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; @@ -473,8 +475,14 @@ public final class space/kscience/kmath/linear/BufferMatrixContext : space/kscie public fun point (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; public fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/Structure2D; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/nd/Structure2D;D)Lspace/kscience/kmath/nd/Structure2D; + public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/linear/BufferMatrix; public synthetic fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; @@ -490,8 +498,8 @@ public final class space/kscience/kmath/linear/BufferMatrixContext : space/kscie public final class space/kscience/kmath/linear/BufferMatrixContext$Companion { } -public final class space/kscience/kmath/linear/BufferVectorGroup : space/kscience/kmath/linear/VectorSpace { - public fun (ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V +public final class space/kscience/kmath/linear/BufferVectorSpace : space/kscience/kmath/linear/VectorSpace { + public fun (ILspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;)V public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -499,7 +507,9 @@ public final class space/kscience/kmath/linear/BufferVectorGroup : space/kscienc public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; - public fun getAlgebra ()Lspace/kscience/kmath/operations/Ring; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun div (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; + public fun getAlgebra ()Lspace/kscience/kmath/operations/Group; public final fun getBufferFactory ()Lkotlin/jvm/functions/Function2; public fun getSize ()I public synthetic fun getZero ()Ljava/lang/Object; @@ -509,7 +519,12 @@ public final class space/kscience/kmath/linear/BufferVectorGroup : space/kscienc public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; - public fun scale (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/structures/Buffer;D)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; @@ -549,12 +564,15 @@ public final class space/kscience/kmath/linear/GenericMatrixContext$DefaultImpls public static fun binaryOperation (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun binaryOperationFunction (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D; + public static fun div (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public static fun dot (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun dot (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static fun minus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun plus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun point (Lspace/kscience/kmath/linear/GenericMatrixContext;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; + public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; public static fun unaryMinus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun unaryOperation (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; @@ -625,7 +643,7 @@ public final class space/kscience/kmath/linear/MatrixBuilderKt { public static final fun row (Lspace/kscience/kmath/nd/Structure2D$Companion;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; } -public abstract interface class space/kscience/kmath/linear/MatrixContext : space/kscience/kmath/operations/GroupOperations { +public abstract interface class space/kscience/kmath/linear/MatrixContext : space/kscience/kmath/operations/GroupOperations, space/kscience/kmath/operations/ScaleOperations { public static final field Companion Lspace/kscience/kmath/linear/MatrixContext$Companion; public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; @@ -645,10 +663,13 @@ public final class space/kscience/kmath/linear/MatrixContext$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun binaryOperationFunction (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D; + public static fun div (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public static fun minus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun plus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun point (Lspace/kscience/kmath/linear/MatrixContext;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; + public static fun times (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun times (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public static fun times (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; public static fun unaryOperation (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun unaryOperationFunction (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public static fun unaryPlus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; @@ -763,21 +784,21 @@ public final class space/kscience/kmath/linear/UnitFeature : space/kscience/kmat public static final field INSTANCE Lspace/kscience/kmath/linear/UnitFeature; } -public abstract interface class space/kscience/kmath/linear/VectorSpace : space/kscience/kmath/operations/Group { +public abstract interface class space/kscience/kmath/linear/VectorSpace : space/kscience/kmath/operations/Group, space/kscience/kmath/operations/ScaleOperations { public static final field Companion Lspace/kscience/kmath/linear/VectorSpace$Companion; public abstract fun add (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun getAlgebra ()Lspace/kscience/kmath/operations/Ring; + public abstract fun getAlgebra ()Lspace/kscience/kmath/operations/Group; public abstract fun getSize ()I public abstract fun getZero ()Lspace/kscience/kmath/structures/Buffer; public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun scale (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun scale (Lspace/kscience/kmath/structures/Buffer;D)Lspace/kscience/kmath/structures/Buffer; public abstract fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; } public final class space/kscience/kmath/linear/VectorSpace$Companion { - public final fun buffered (ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferVectorGroup; - public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/VectorSpace$Companion;ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/BufferVectorGroup; - public final fun real (I)Lspace/kscience/kmath/linear/BufferVectorGroup; + public final fun buffered (ILspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferVectorSpace; + public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/VectorSpace$Companion;ILspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/BufferVectorSpace; + public final fun real (I)Lspace/kscience/kmath/linear/BufferVectorSpace; } public final class space/kscience/kmath/linear/VectorSpace$DefaultImpls { @@ -785,10 +806,13 @@ public final class space/kscience/kmath/linear/VectorSpace$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static fun binaryOperationFunction (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; + public static fun div (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public static fun getZero (Lspace/kscience/kmath/linear/VectorSpace;)Lspace/kscience/kmath/structures/Buffer; public static fun minus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static fun plus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun scale (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; + public static fun scale (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;D)Lspace/kscience/kmath/structures/Buffer; + public static fun times (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public static fun times (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public static fun unaryMinus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static fun unaryOperation (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static fun unaryOperationFunction (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt index ef1d82795..ba7b7358c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt @@ -3,6 +3,7 @@ package space.kscience.kmath.linear import space.kscience.kmath.nd.NDStructure import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory @@ -18,15 +19,22 @@ public typealias Matrix = Structure2D /** * Basic implementation of Matrix space based on [NDStructure] */ -public class BufferMatrixContext>( - public override val elementContext: R, +public class BufferMatrixContext( + public override val elementContext: A, private val bufferFactory: BufferFactory, -) : GenericMatrixContext> { +) : GenericMatrixContext> where A : Ring, A : ScaleOperations { + public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): BufferMatrix { val buffer = bufferFactory(rows * columns) { offset -> initializer(offset / columns, offset % columns) } return BufferMatrix(rows, columns, buffer) } + override fun scale(a: Matrix, value: Double): Matrix = elementContext { + produce(a.rowNum, a.colNum) { i, j -> + a[i, j] * value + } + } + public override fun point(size: Int, initializer: (Int) -> T): Point = bufferFactory(size, initializer) private fun Matrix.toBufferMatrix(): BufferMatrix = if (this is BufferMatrix) this else { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt index b8937885a..6afec94e8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt @@ -13,7 +13,7 @@ import kotlin.reflect.KClass * @param T the type of items in the matrices. * @param M the type of operated matrices. */ -public interface MatrixContext> : GroupOperations> { +public interface MatrixContext> : GroupOperations>, ScaleOperations> { /** * Produces a matrix with this context and given dimensions. */ @@ -28,7 +28,7 @@ public interface MatrixContext> : GroupOperations, right: Matrix) -> M = when (operation) { "dot" -> { left, right -> left dot right } - else -> super.binaryOperationFunction(operation) as (Matrix, Matrix) -> M + else -> super.binaryOperationFunction(operation) as (Matrix, Matrix) -> M } /** @@ -84,15 +84,15 @@ public interface MatrixContext> : GroupOperations> buffered( - ring: R, + public fun buffered( + ring: A, bufferFactory: BufferFactory = Buffer.Companion::boxing, - ): GenericMatrixContext> = BufferMatrixContext(ring, bufferFactory) + ): GenericMatrixContext> where A : Ring, A: ScaleOperations = BufferMatrixContext(ring, bufferFactory) /** * Automatic buffered matrix, unboxed if it is possible */ - public inline fun > auto(ring: R): GenericMatrixContext> = + public inline fun auto(ring: A): GenericMatrixContext> where A : Ring, A: ScaleOperations = buffered(ring, Buffer.Companion::auto) } } @@ -116,14 +116,14 @@ public inline fun MatrixContext.getFeature(m: M * Partial implementation of [MatrixContext] for matrices of [Ring]. * * @param T the type of items in the matrices. - * @param R the type of ring of matrix elements. + * @param A the type of ring of matrix elements. * @param M the type of operated matrices. */ -public interface GenericMatrixContext, out M : Matrix> : MatrixContext { +public interface GenericMatrixContext> : MatrixContext where A : Ring, A : ScaleOperations{ /** * The ring over matrix elements. */ - public val elementContext: R + public val elementContext: A public override infix fun Matrix.dot(other: Matrix): M { //TODO add typed error diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt index 86ec0de88..69e4a916f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt @@ -4,6 +4,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.getFeature import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.structures.asBuffer import kotlin.math.sqrt import kotlin.reflect.KClass @@ -14,7 +15,7 @@ import kotlin.reflect.safeCast * * @param T the type of items. */ -public class MatrixWrapper internal constructor( +public class MatrixWrapper internal constructor( public val origin: Matrix, public val features: Set, ) : Matrix by origin { @@ -73,17 +74,23 @@ public fun Structure2D.Companion.square(vararg elements: T): Matrix /** * Diagonal matrix of ones. The matrix is virtual no actual matrix is created */ -public fun > GenericMatrixContext.one(rows: Int, columns: Int): Matrix = - VirtualMatrix(rows, columns) { i, j -> - if (i == j) elementContext.one else elementContext.zero - } + UnitFeature +public fun GenericMatrixContext.one( + rows: Int, + columns: Int, +): Matrix where A : Ring, A : ScaleOperations = VirtualMatrix(rows, columns) { i, j -> + if (i == j) elementContext.one else elementContext.zero +} + UnitFeature /** * A virtual matrix of zeroes */ -public fun > GenericMatrixContext.zero(rows: Int, columns: Int): Matrix = - VirtualMatrix(rows, columns) { _, _ -> elementContext.zero } + ZeroFeature +public fun GenericMatrixContext.zero( + rows: Int, + columns: Int, +): Matrix where A : Ring, A : ScaleOperations = VirtualMatrix(rows, columns) { _, _ -> + elementContext.zero +} + ZeroFeature public class TransposedFeature(public val original: Matrix) : MatrixFeature @@ -91,9 +98,7 @@ public class TransposedFeature(public val original: Matrix) : Matrix * Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A` */ @OptIn(UnstableKMathAPI::class) -public fun Matrix.transpose(): Matrix { - return getFeature>()?.original ?: VirtualMatrix( - colNum, - rowNum, - ) { i, j -> get(j, i) } + TransposedFeature(this) -} \ No newline at end of file +public fun Matrix.transpose(): Matrix = getFeature>()?.original ?: VirtualMatrix( + colNum, + rowNum, +) { i, j -> get(j, i) } + TransposedFeature(this) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt index 570c87b81..cfacf6826 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.linear import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.RealField -import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory @@ -11,7 +11,8 @@ import space.kscience.kmath.structures.BufferFactory * A linear space for vectors. * Could be used on any point-like structure */ -public interface VectorSpace> : Group> { +public interface VectorSpace : Group>, ScaleOperations> + where A : Group, A : ScaleOperations { public val size: Int public val algebra: A override val zero: Point get() = produce { algebra.zero } @@ -20,20 +21,20 @@ public interface VectorSpace> : Group> { override fun add(a: Point, b: Point): Point = produce { algebra { a[it] + b[it] } } - public fun scale(a: Point, scale: T): Point = produce { algebra { a[it] * scale } } + override fun scale(a: Point, value: Double): Point = produce { algebra.scale(a[it], value) } override fun Point.unaryMinus(): Point = produce { -get(it) } //TODO add basis public companion object { - private val realSpaceCache: MutableMap> = hashMapOf() + private val realSpaceCache: MutableMap> = hashMapOf() /** * Non-boxing double vector space */ - public fun real(size: Int): BufferVectorGroup = realSpaceCache.getOrPut(size) { - BufferVectorGroup( + public fun real(size: Int): BufferVectorSpace = realSpaceCache.getOrPut(size) { + BufferVectorSpace( size, RealField, Buffer.Companion::auto @@ -43,25 +44,29 @@ public interface VectorSpace> : Group> { /** * A structured vector space with custom buffer */ - public fun > buffered( + public fun buffered( size: Int, space: A, bufferFactory: BufferFactory = Buffer.Companion::boxing, - ): BufferVectorGroup = BufferVectorGroup(size, space, bufferFactory) + ): BufferVectorSpace where A : Group, A : ScaleOperations = + BufferVectorSpace(size, space, bufferFactory) /** * Automatic buffered vector, unboxed if it is possible */ - public inline fun > auto(size: Int, space: A): VectorSpace = + public inline fun auto( + size: Int, + space: A, + ): VectorSpace where A : Group, A : ScaleOperations = buffered(size, space, Buffer.Companion::auto) } } -public class BufferVectorGroup>( +public class BufferVectorSpace( override val size: Int, override val algebra: A, public val bufferFactory: BufferFactory, -) : VectorSpace { +) : VectorSpace where A : Group, A : ScaleOperations { override fun produce(initializer: A.(Int) -> T): Buffer = bufferFactory(size) { algebra.initializer(it) } } diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt index 808bd692f..9552c1320 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt @@ -1,10 +1,11 @@ package space.kscience.kmath.geometry import space.kscience.kmath.operations.Group +import space.kscience.kmath.operations.ScaleOperations public interface Vector -public interface GeometrySpace : Group { +public interface GeometrySpace : Group, ScaleOperations { /** * L2 distance */ From 723e0e458e7be15e3388e4bef6654db487d2cf03 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 11 Mar 2021 23:04:42 +0300 Subject: [PATCH 045/393] add functions transpose and transposeAssign --- .../space/kscience/kmath/nd/NDStructure.kt | 9 ++++ .../kmath/tensors/RealTensorAlgebra.kt | 26 +++++++++- .../kscience/kmath/tensors/TensorStrides.kt | 20 ++++++++ .../kmath/tensors/TestRealTensorAlgebra.kt | 51 +++++++++++++++++++ 4 files changed, 104 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt index 54e410ade..e458d0606 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt @@ -174,6 +174,11 @@ public interface Strides { */ public fun index(offset: Int): IntArray + /** + * Get next multidimensional index from the current multidimensional index + */ + public fun nextIndex(index: IntArray): IntArray + /** * The size of linear buffer to accommodate all elements of ND-structure corresponding to strides */ @@ -232,6 +237,10 @@ public class DefaultStrides private constructor(override val shape: IntArray) : return res } + override fun nextIndex(index: IntArray): IntArray { + TODO("Not yet implemented") + } + override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is DefaultStrides) return false diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 366acfb62..a5c00e8ec 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -164,11 +164,33 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra= shape[current]) { + carry = 1 + res[current] = 0 + } + current-- + } while(carry != 0 && current >= 0) + + return res +} + public class TensorStrides(override val shape: IntArray): Strides @@ -47,6 +64,9 @@ public class TensorStrides(override val shape: IntArray): Strides override fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) + override fun nextIndex(index: IntArray): IntArray = + nextIndex(index, shape, shape.size) + override val linearSize: Int get() = shape.reduce(Int::times) } \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index 86caa0338..8e95922b8 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -13,4 +13,55 @@ class TestRealTensorAlgebra { assertTrue(res.buffer.array contentEquals doubleArrayOf(11.0,12.0)) } + @Test + fun transpose1x1() = RealTensorAlgebra { + val tensor = RealTensor(intArrayOf(1), doubleArrayOf(0.0)) + val res = tensor.transpose(0, 0) + + assertTrue(res.buffer.array contentEquals doubleArrayOf(0.0)) + assertTrue(res.shape contentEquals intArrayOf(1)) + } + + @Test + fun transpose3x2() = RealTensorAlgebra { + val tensor = RealTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val res = tensor.transpose(1, 0) + + assertTrue(res.buffer.array contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) + assertTrue(res.shape contentEquals intArrayOf(2, 3)) + } + + @Test + fun transpose1x2x3() = RealTensorAlgebra { + val tensor = RealTensor(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val res01 = tensor.transpose(0, 1) + val res02 = tensor.transpose(0, 2) + val res12 = tensor.transpose(1, 2) + + assertTrue(res01.shape contentEquals intArrayOf(2, 1, 3)) + assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) + assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2)) + + assertTrue(res01.buffer.array contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res02.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res12.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + } + + @Test + fun transposeAssign1x2() = RealTensorAlgebra { + val tensor = RealTensor(intArrayOf(1,2), doubleArrayOf(1.0, 2.0)) + tensor.transposeAssign(0, 1) + + assertTrue(tensor.buffer.array contentEquals doubleArrayOf(1.0, 2.0)) + assertTrue(tensor.shape contentEquals intArrayOf(2, 1)) + } + + @Test + fun transposeAssign2x3() = RealTensorAlgebra { + val tensor = RealTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + tensor.transposeAssign(1, 0) + + assertTrue(tensor.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(tensor.shape contentEquals intArrayOf(3, 2)) + } } \ No newline at end of file From bb4894b87ea5d4ed64b290ae0ddcd35c9ebe6d1a Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 11 Mar 2021 21:46:35 +0000 Subject: [PATCH 046/393] removing assignement for non operator members --- .../kmath/tensors/RealTensorAlgebra.kt | 31 +------------------ .../kscience/kmath/tensors/TensorAlgebra.kt | 7 ----- .../kmath/tensors/TestRealTensorAlgebra.kt | 18 ----------- 3 files changed, 1 insertion(+), 55 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index a5c00e8ec..16f90341b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -151,14 +151,6 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { TODO() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 6f42623e0..f1d401f6e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -35,8 +35,6 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.matmul.html public infix fun TensorType.dot(other: TensorType): TensorType - public infix fun TensorType.dotAssign(other: TensorType): Unit - public infix fun TensorType.dotRightAssign(other: TensorType): Unit //https://pytorch.org/docs/stable/generated/torch.diag_embed.html public fun diagonalEmbedding( @@ -46,7 +44,6 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.transpose.html public fun TensorType.transpose(i: Int, j: Int): TensorType - public fun TensorType.transposeAssign(i: Int, j: Int): Unit //https://pytorch.org/docs/stable/tensor_view.html public fun TensorType.view(shape: IntArray): TensorType @@ -54,11 +51,9 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.abs.html public fun TensorType.abs(): TensorType - public fun TensorType.absAssign(): Unit //https://pytorch.org/docs/stable/generated/torch.sum.html public fun TensorType.sum(): TensorType - public fun TensorType.sumAssign(): Unit } // https://proofwiki.org/wiki/Definition:Division_Algebra @@ -72,11 +67,9 @@ public interface TensorPartialDivisionAlgebra //https://pytorch.org/docs/stable/generated/torch.exp.html public fun TensorType.exp(): TensorType - public fun TensorType.expAssign(): Unit //https://pytorch.org/docs/stable/generated/torch.log.html public fun TensorType.log(): TensorType - public fun TensorType.logAssign(): Unit //https://pytorch.org/docs/stable/generated/torch.lu.html public fun TensorType.lu(): Pair diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index 8e95922b8..19f0c0ef0 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -46,22 +46,4 @@ class TestRealTensorAlgebra { assertTrue(res02.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) assertTrue(res12.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) } - - @Test - fun transposeAssign1x2() = RealTensorAlgebra { - val tensor = RealTensor(intArrayOf(1,2), doubleArrayOf(1.0, 2.0)) - tensor.transposeAssign(0, 1) - - assertTrue(tensor.buffer.array contentEquals doubleArrayOf(1.0, 2.0)) - assertTrue(tensor.shape contentEquals intArrayOf(2, 1)) - } - - @Test - fun transposeAssign2x3() = RealTensorAlgebra { - val tensor = RealTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - tensor.transposeAssign(1, 0) - - assertTrue(tensor.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) - assertTrue(tensor.shape contentEquals intArrayOf(3, 2)) - } } \ No newline at end of file From f9500f44ec6fc811a17e76104a9bea7ed6f790cc Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 12 Mar 2021 13:50:06 +0300 Subject: [PATCH 047/393] new tensor def --- .../kscience/kmath/tensors/BufferTensor.kt | 28 +++++++++++++++++++ .../kmath/tensors/RealTensorAlgebra.kt | 14 +++++----- 2 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt new file mode 100644 index 000000000..4d8aea32c --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt @@ -0,0 +1,28 @@ +package space.kscience.kmath.tensors + +import space.kscience.kmath.linear.BufferMatrix +import space.kscience.kmath.linear.RealMatrixContext.toBufferMatrix +import space.kscience.kmath.nd.MutableNDBuffer +import space.kscience.kmath.nd.as2D +import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.toList + +public open class BufferTensor( + override val shape: IntArray, + buffer: MutableBuffer +) : + TensorStructure, + MutableNDBuffer( + TensorStrides(shape), + buffer + ) + + +public fun BufferTensor.toBufferMatrix(): BufferMatrix { + return BufferMatrix(shape[0], shape[1], this.buffer) +} + +public fun BufferMatrix.BufferTensor(): BufferTensor { + return BufferTensor(intArrayOf(rowNum, colNum), buffer) +} + diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index a5c00e8ec..e38056097 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,19 +1,19 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.linear.BufferMatrix +import space.kscience.kmath.linear.RealMatrixContext.toBufferMatrix import space.kscience.kmath.nd.MutableNDBuffer +import space.kscience.kmath.nd.as2D +import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array +import space.kscience.kmath.structures.toList public class RealTensor( - override val shape: IntArray, + shape: IntArray, buffer: DoubleArray -) : - TensorStructure, - MutableNDBuffer( - TensorStrides(shape), - RealBuffer(buffer) - ) +) : BufferTensor(shape, RealBuffer(buffer)) public class RealTensorAlgebra : TensorPartialDivisionAlgebra { From 95b814e1637c281b6cc771b0c89e3475a27323c9 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 12 Mar 2021 14:29:51 +0300 Subject: [PATCH 048/393] add fromMatrix --- .../kotlin/space/kscience/kmath/tensors/BufferTensor.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt index 4d8aea32c..817c51f11 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt @@ -2,8 +2,12 @@ package space.kscience.kmath.tensors import space.kscience.kmath.linear.BufferMatrix import space.kscience.kmath.linear.RealMatrixContext.toBufferMatrix +import space.kscience.kmath.nd.Matrix import space.kscience.kmath.nd.MutableNDBuffer +import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferAccessor2D import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.toList @@ -22,7 +26,8 @@ public fun BufferTensor.toBufferMatrix(): BufferMatrix { return BufferMatrix(shape[0], shape[1], this.buffer) } -public fun BufferMatrix.BufferTensor(): BufferTensor { - return BufferTensor(intArrayOf(rowNum, colNum), buffer) +// T??? +public fun BufferMatrix.BufferTensor(): BufferTensor { + return BufferTensor(intArrayOf(rowNum, colNum), BufferAccessor2D(rowNum, colNum, Buffer.Companion::real).create(this)) } From 993bba3133581498865ed71cbe22a303a879b58e Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 12 Mar 2021 19:03:56 +0700 Subject: [PATCH 049/393] Fix #226 --- .../kotlin/space/kscience/kmath/misc/cumulative.kt | 12 ++++++------ .../kscience/kmath/operations/algebraExtensions.kt | 12 ++++++------ .../kotlin/space/kscience/kmath/chains/flowExtra.kt | 2 +- .../kotlin/space/kscience/kmath/histogram/Counter.kt | 9 +++++---- .../kotlin/space/kscience/kmath/stat/Statistic.kt | 8 ++++---- 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt index b50e095cf..6466695a6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt @@ -37,8 +37,8 @@ public fun List.cumulative(initial: R, operation: (R, T) -> R): List Iterable.cumulativeSum(space: Group): Iterable = - space { cumulative(zero) { element: T, sum: T -> sum + element } } +public fun Iterable.cumulativeSum(group: Group): Iterable = + group { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") public fun Iterable.cumulativeSum(): Iterable = cumulative(0.0) { element, sum -> sum + element } @@ -49,8 +49,8 @@ public fun Iterable.cumulativeSum(): Iterable = cumulative(0) { elemen @JvmName("cumulativeSumOfLong") public fun Iterable.cumulativeSum(): Iterable = cumulative(0L) { element, sum -> sum + element } -public fun Sequence.cumulativeSum(space: Group): Sequence = - space { cumulative(zero) { element: T, sum: T -> sum + element } } +public fun Sequence.cumulativeSum(group: Group): Sequence = + group { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") public fun Sequence.cumulativeSum(): Sequence = cumulative(0.0) { element, sum -> sum + element } @@ -61,8 +61,8 @@ public fun Sequence.cumulativeSum(): Sequence = cumulative(0) { elemen @JvmName("cumulativeSumOfLong") public fun Sequence.cumulativeSum(): Sequence = cumulative(0L) { element, sum -> sum + element } -public fun List.cumulativeSum(space: Group): List = - space { cumulative(zero) { element: T, sum: T -> sum + element } } +public fun List.cumulativeSum(group: Group): List = + group { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") public fun List.cumulativeSum(): List = cumulative(0.0) { element, sum -> sum + element } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 52a0dec6f..b927655e3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -49,19 +49,19 @@ public fun > Group.abs(value: T): T = if (value > zero) val * Returns the sum of all elements in the iterable in provided space. * * @receiver the collection to sum up. - * @param space the algebra that provides addition. + * @param group the algebra that provides addition. * @return the sum. */ -public fun Iterable.sumWith(space: Group): T = space.sum(this) +public fun Iterable.sumWith(group: Group): T = group.sum(this) /** * Returns the sum of all elements in the sequence in provided space. * * @receiver the collection to sum up. - * @param space the algebra that provides addition. + * @param group the algebra that provides addition. * @return the sum. */ -public fun Sequence.sumWith(space: Group): T = space.sum(this) +public fun Sequence.sumWith(group: Group): T = group.sum(this) /** * Returns an average value of elements in the iterable in this [Group]. @@ -71,7 +71,7 @@ public fun Sequence.sumWith(space: Group): T = space.sum(this) * @return the average value. * @author Iaroslav Postovalov */ -public fun Iterable.averageWith(space: S): T where S : Group, S : ScaleOperations = +public fun Iterable.averageWith(space: S): T where S : Group, S : ScaleOperations = space.average(this) /** @@ -82,7 +82,7 @@ public fun Iterable.averageWith(space: S): T where S : Group, S : * @return the average value. * @author Iaroslav Postovalov */ -public fun Sequence.averageWith(space: S): T where S : Group, S : ScaleOperations = +public fun Sequence.averageWith(space: S): T where S : Group, S : ScaleOperations = space.average(this) //TODO optimized power operation diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt index 81b4327fc..7d4914a01 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt @@ -14,7 +14,7 @@ public fun Flow.cumulativeSum(group: GroupOperations): Flow = group { runningReduce { sum, element -> sum + element } } @ExperimentalCoroutinesApi -public fun Flow.mean(algebra: S): Flow where S : Group, S : ScaleOperations = algebra { +public fun Flow.mean(space: S): Flow where S : Group, S : ScaleOperations = space { data class Accumulator(var sum: T, var num: Int) scan(Accumulator(zero, 0)) { sum, element -> diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt index d5f3965d9..5f79fdab8 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt @@ -11,7 +11,8 @@ import space.kscience.kmath.operations.RealField public interface Counter { public fun add(delta: T) public val value: T - public companion object{ + + public companion object { public fun real(): ObjectCounter = ObjectCounter(RealField) } } @@ -36,11 +37,11 @@ public class LongCounter : Counter { override val value: Long get() = innerValue.value } -public class ObjectCounter(public val space: Group) : Counter { - private val innerValue = atomic(space.zero) +public class ObjectCounter(public val group: Group) : Counter { + private val innerValue = atomic(group.zero) override fun add(delta: T) { - innerValue.getAndUpdate { space.run { it + delta } } + innerValue.getAndUpdate { group.run { it + delta } } } override val value: T get() = innerValue.value diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt index a9f7cd3e4..6fe0fee9b 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt @@ -66,16 +66,16 @@ public fun ComposableStatistic.flow( * Arithmetic mean */ public class Mean( - private val space: Group, + private val group: Group, private val division: (sum: T, count: Int) -> T, ) : ComposableStatistic, T> { public override suspend fun computeIntermediate(data: Buffer): Pair = - space { sum(data.asIterable()) } to data.size + group { sum(data.asIterable()) } to data.size public override suspend fun composeIntermediate(first: Pair, second: Pair): Pair = - space { first.first + second.first } to (first.second + second.second) + group { first.first + second.first } to (first.second + second.second) - public override suspend fun toResult(intermediate: Pair): T = space { + public override suspend fun toResult(intermediate: Pair): T = group { division(intermediate.first, intermediate.second) } From 454d574ccd8876982753e8e09782ff1f4fb0c564 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Fri, 12 Mar 2021 15:20:46 +0300 Subject: [PATCH 050/393] add broadcast and functions plus and minus --- .../kmath/tensors/RealTensorAlgebra.kt | 96 ++++++++++++++++--- .../kscience/kmath/tensors/TensorAlgebra.kt | 3 + .../kmath/tensors/TestRealTensorAlgebra.kt | 47 +++++++++ 3 files changed, 135 insertions(+), 11 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index a5c00e8ec..a4ad54bfc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -2,7 +2,9 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.structures.ValueFlag import space.kscience.kmath.structures.array +import kotlin.math.max public class RealTensor( @@ -54,27 +56,85 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { + val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) + val n = totalShape.reduce{ acc, i -> acc * i } + + val res = ArrayList(0) + for (tensor in tensors) { + val resTensor = RealTensor(totalShape, DoubleArray(n)) + + for (linearIndex in 0 until n) { + val totalMultiIndex = resTensor.strides.index(linearIndex) + val curMultiIndex = tensor.shape.copyOf() + + val offset = totalMultiIndex.size - curMultiIndex.size + + for (i in curMultiIndex.indices) { + if (curMultiIndex[i] != 1) { + curMultiIndex[i] = totalMultiIndex[i + offset] + } else { + curMultiIndex[i] = 0 + } + } + + val curLinearIndex = tensor.strides.offset(curMultiIndex) + resTensor.buffer.array[linearIndex] = tensor.buffer.array[curLinearIndex] + } + res.add(resTensor) + } + + return res + } + override fun Double.plus(other: RealTensor): RealTensor { - //todo should be change with broadcasting val resBuffer = DoubleArray(other.buffer.size) { i -> other.buffer.array[i] + this } return RealTensor(other.shape, resBuffer) } - //todo should be change with broadcasting override fun RealTensor.plus(value: Double): RealTensor = value + this override fun RealTensor.plus(other: RealTensor): RealTensor { - //todo should be change with broadcasting - val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.array[i] + other.buffer.array[i] + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.buffer.size) { i -> + newThis.buffer.array[i] + newOther.buffer.array[i] } - return RealTensor(this.shape, resBuffer) + return RealTensor(newThis.shape, resBuffer) } override fun RealTensor.plusAssign(value: Double) { - //todo should be change with broadcasting for (i in this.buffer.array.indices) { this.buffer.array[i] += value } @@ -88,19 +148,33 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra + this - other.buffer.array[i] + } + return RealTensor(other.shape, resBuffer) } override fun RealTensor.minus(value: Double): RealTensor { - TODO("Alya") + val resBuffer = DoubleArray(this.buffer.size) { i -> + this.buffer.array[i] - value + } + return RealTensor(this.shape, resBuffer) } override fun RealTensor.minus(other: RealTensor): RealTensor { - TODO("Alya") + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.buffer.size) { i -> + newThis.buffer.array[i] - newOther.buffer.array[i] + } + return RealTensor(newThis.shape, resBuffer) } override fun RealTensor.minusAssign(value: Double) { - TODO("Alya") + for (i in this.buffer.array.indices) { + this.buffer.array[i] -= value + } } override fun RealTensor.minusAssign(other: RealTensor) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 6f42623e0..bd47a1b76 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -13,6 +13,9 @@ public interface TensorAlgebra> { public fun TensorType.copy(): TensorType + public fun broadcastShapes(vararg shapes: IntArray): IntArray + public fun broadcastTensors(vararg tensors: RealTensor): List + public operator fun T.plus(other: TensorType): TensorType public operator fun TensorType.plus(value: T): TensorType public operator fun TensorType.plus(other: TensorType): TensorType diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index 8e95922b8..18639bf3c 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -2,6 +2,8 @@ package space.kscience.kmath.tensors import space.kscience.kmath.structures.array import kotlin.test.Test +import kotlin.test.assertFails +import kotlin.test.assertFailsWith import kotlin.test.assertTrue class TestRealTensorAlgebra { @@ -64,4 +66,49 @@ class TestRealTensorAlgebra { assertTrue(tensor.buffer.array contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) assertTrue(tensor.shape contentEquals intArrayOf(3, 2)) } + + @Test + fun broadcastShapes() = RealTensorAlgebra { + assertTrue(this.broadcastShapes( + intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) + ) contentEquals intArrayOf(1, 2, 3)) + + assertTrue(this.broadcastShapes( + intArrayOf(6, 7), intArrayOf(5, 6, 1), intArrayOf(7,), intArrayOf(5, 1, 7) + ) contentEquals intArrayOf(5, 6, 7)) + } + + @Test + fun broadcastTensors() = RealTensorAlgebra { + val tensor1 = RealTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = RealTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + + val res = this.broadcastTensors(tensor1, tensor2, tensor3) + + assertTrue(res[0].shape contentEquals intArrayOf(1, 2, 3)) + assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) + assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) + + assertTrue(res[0].buffer.array contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].buffer.array contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + assertTrue(res[2].buffer.array contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) + } + + @Test + fun minusTensor() = RealTensorAlgebra { + val tensor1 = RealTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = RealTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + + assertTrue((tensor2 - tensor1).shape contentEquals intArrayOf(2, 3)) + assertTrue((tensor2 - tensor1).buffer.array contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) + + assertTrue((tensor3 - tensor1).shape contentEquals intArrayOf(1, 2, 3)) + assertTrue((tensor3 - tensor1).buffer.array + contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0)) + + assertTrue((tensor3 - tensor2).shape contentEquals intArrayOf(1, 1, 3)) + assertTrue((tensor3 - tensor2).buffer.array contentEquals doubleArrayOf(490.0, 480.0, 470.0)) + } } \ No newline at end of file From 70e1861e536febfe9792fcbd3dde3dbd66cb4682 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Fri, 12 Mar 2021 15:25:47 +0300 Subject: [PATCH 051/393] remove extra import --- .../kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index a4ad54bfc..afe78ae08 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -2,7 +2,6 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.RealBuffer -import space.kscience.kmath.structures.ValueFlag import space.kscience.kmath.structures.array import kotlin.math.max From 626d5c98fa843fe6833cf300f8b71871d54474b1 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Fri, 12 Mar 2021 15:43:44 +0300 Subject: [PATCH 052/393] change IllegalArgumentException to RuntimeException --- .../kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index afe78ae08..9e090e376 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -75,7 +75,7 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra Date: Fri, 12 Mar 2021 19:23:01 +0700 Subject: [PATCH 053/393] Improve conversion functions for Buffer --- kmath-core/api/kmath-core.api | 11 ++++---- .../space/kscience/kmath/structures/Buffer.kt | 26 ++++++++++++++++--- .../kscience/kmath/structures/FloatBuffer.kt | 8 +++--- .../kscience/kmath/structures/IntBuffer.kt | 8 +++--- .../kscience/kmath/structures/LongBuffer.kt | 8 +++--- .../kscience/kmath/structures/RealBuffer.kt | 8 +++--- .../kscience/kmath/structures/ShortBuffer.kt | 8 +++--- 7 files changed, 54 insertions(+), 23 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 8b30e4c05..d19c2c640 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2314,6 +2314,7 @@ public final class space/kscience/kmath/structures/BufferKt { public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence; public static final fun getIndices (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/ranges/IntRange; public static final fun toList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List; + public static final fun toMutableList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List; } public abstract interface class space/kscience/kmath/structures/FlaggedBuffer : space/kscience/kmath/structures/Buffer { @@ -2376,7 +2377,7 @@ public final class space/kscience/kmath/structures/FloatBufferKt { public static final fun FloatBuffer (ILkotlin/jvm/functions/Function1;)[F public static final fun FloatBuffer ([F)[F public static final fun asBuffer ([F)[F - public static final fun getArray (Lspace/kscience/kmath/structures/MutableBuffer;)[F + public static final fun toFloatArray (Lspace/kscience/kmath/structures/Buffer;)[F } public final class space/kscience/kmath/structures/IntBuffer : space/kscience/kmath/structures/MutableBuffer { @@ -2412,7 +2413,7 @@ public final class space/kscience/kmath/structures/IntBufferKt { public static final fun IntBuffer (ILkotlin/jvm/functions/Function1;)[I public static final fun IntBuffer ([I)[I public static final fun asBuffer ([I)[I - public static final fun getArray (Lspace/kscience/kmath/structures/MutableBuffer;)[I + public static final fun toIntArray (Lspace/kscience/kmath/structures/Buffer;)[I } public final class space/kscience/kmath/structures/ListBuffer : space/kscience/kmath/structures/Buffer { @@ -2470,7 +2471,7 @@ public final class space/kscience/kmath/structures/LongBufferKt { public static final fun LongBuffer (ILkotlin/jvm/functions/Function1;)[J public static final fun LongBuffer ([J)[J public static final fun asBuffer ([J)[J - public static final fun getArray (Lspace/kscience/kmath/structures/MutableBuffer;)[J + public static final fun toLongArray (Lspace/kscience/kmath/structures/Buffer;)[J } public class space/kscience/kmath/structures/MemoryBuffer : space/kscience/kmath/structures/Buffer { @@ -2749,7 +2750,7 @@ public final class space/kscience/kmath/structures/RealBufferKt { public static final fun RealBuffer ([D)[D public static final fun asBuffer ([D)[D public static final fun contentEquals-2uVC2J0 ([D[D)Z - public static final fun getArray (Lspace/kscience/kmath/structures/MutableBuffer;)[D + public static final fun toDoubleArray (Lspace/kscience/kmath/structures/Buffer;)[D } public final class space/kscience/kmath/structures/ShortBuffer : space/kscience/kmath/structures/MutableBuffer { @@ -2785,7 +2786,7 @@ public final class space/kscience/kmath/structures/ShortBufferKt { public static final fun ShortBuffer (ILkotlin/jvm/functions/Function1;)[S public static final fun ShortBuffer ([S)[S public static final fun asBuffer ([S)[S - public static final fun getArray (Lspace/kscience/kmath/structures/MutableBuffer;)[S + public static final fun toShortArray (Lspace/kscience/kmath/structures/Buffer;)[S } public final class space/kscience/kmath/structures/ValueFlag : java/lang/Enum { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 2fccd2eeb..2bde18fce 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -100,9 +100,29 @@ public fun Buffer.asSequence(): Sequence = Sequence(::iterator) public fun Buffer.asIterable(): Iterable = Iterable(::iterator) /** - * Converts this [Buffer] to a new [List] + * Returns a new [List] containing all elements of this buffer. */ -public fun Buffer.toList(): List = asSequence().toList() +public fun Buffer.toList(): List = when (this) { + is ArrayBuffer -> array.toList() + is ListBuffer -> list.toList() + is MutableListBuffer -> list.toList() + else -> asSequence().toList() +} + +/** + * Returns a new [MutableList] filled with all elements of this buffer. + */ +public fun Buffer.toMutableList(): MutableList = when (this) { + is ArrayBuffer -> array.toMutableList() + is ListBuffer -> list.toMutableList() + is MutableListBuffer -> list.toMutableList() + else -> asSequence().toMutableList() +} + +/** + * Returns a new [Array] containing all elements of this buffer. + */ +public inline fun Buffer.toTypedArray(): Array = asSequence().toList().toTypedArray() /** * Returns an [IntRange] of the valid indices for this [Buffer]. @@ -222,7 +242,7 @@ public inline class MutableListBuffer(public val list: MutableList) : Muta * @param T the type of elements contained in the buffer. * @property array The underlying array. */ -public class ArrayBuffer(private val array: Array) : MutableBuffer { +public class ArrayBuffer(internal val array: Array) : MutableBuffer { // Can't inline because array is invariant override val size: Int get() = array.size diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt index 3839be8e1..9fc7d55f3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt @@ -36,10 +36,12 @@ public inline fun FloatBuffer(size: Int, init: (Int) -> Float): FloatBuffer = Fl public fun FloatBuffer(vararg floats: Float): FloatBuffer = FloatBuffer(floats) /** - * Returns a [FloatArray] containing all of the elements of this [MutableBuffer]. + * Returns a new [FloatArray] containing all of the elements of this [Buffer]. */ -public val MutableBuffer.array: FloatArray - get() = (if (this is FloatBuffer) array else FloatArray(size) { get(it) }) +public fun Buffer.toFloatArray(): FloatArray = when(this) { + is FloatBuffer -> array.copyOf() + else -> FloatArray(size, ::get) +} /** * Returns [FloatBuffer] over this array. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt index df3289a3e..d3d0f79a5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt @@ -35,10 +35,12 @@ public inline fun IntBuffer(size: Int, init: (Int) -> Int): IntBuffer = IntBuffe public fun IntBuffer(vararg ints: Int): IntBuffer = IntBuffer(ints) /** - * Returns a [IntArray] containing all of the elements of this [MutableBuffer]. + * Returns a new [IntArray] containing all of the elements of this [Buffer]. */ -public val MutableBuffer.array: IntArray - get() = (if (this is IntBuffer) array else IntArray(size) { get(it) }) +public fun Buffer.toIntArray(): IntArray = when(this) { + is IntBuffer -> array.copyOf() + else -> IntArray(size, ::get) +} /** * Returns [IntBuffer] over this array. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt index d07d44799..fec358421 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt @@ -35,10 +35,12 @@ public inline fun LongBuffer(size: Int, init: (Int) -> Long): LongBuffer = LongB public fun LongBuffer(vararg longs: Long): LongBuffer = LongBuffer(longs) /** - * Returns a [IntArray] containing all of the elements of this [MutableBuffer]. + * Returns a new [LongArray] containing all of the elements of this [Buffer]. */ -public val MutableBuffer.array: LongArray - get() = (if (this is LongBuffer) array else LongArray(size) { get(it) }) +public fun Buffer.toLongArray(): LongArray = when(this) { + is LongBuffer -> array.copyOf() + else -> LongArray(size, ::get) +} /** * Returns [LongBuffer] over this array. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt index e53ed85c7..01b533138 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt @@ -40,10 +40,12 @@ public fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles) public fun RealBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles) /** - * Returns a [DoubleArray] containing all of the elements of this [MutableBuffer]. + * Returns a new [DoubleArray] containing all of the elements of this [Buffer]. */ -public val MutableBuffer.array: DoubleArray - get() = (if (this is RealBuffer) array else DoubleArray(size) { get(it) }) +public fun Buffer.toDoubleArray(): DoubleArray = when(this) { + is RealBuffer -> array.copyOf() + else -> DoubleArray(size, ::get) +} /** * Returns [RealBuffer] over this array. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt index afc472b72..77f128403 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt @@ -33,10 +33,12 @@ public inline fun ShortBuffer(size: Int, init: (Int) -> Short): ShortBuffer = Sh public fun ShortBuffer(vararg shorts: Short): ShortBuffer = ShortBuffer(shorts) /** - * Returns a [ShortArray] containing all of the elements of this [MutableBuffer]. + * Returns a new [ShortArray] containing all of the elements of this [Buffer]. */ -public val MutableBuffer.array: ShortArray - get() = (if (this is ShortBuffer) array else ShortArray(size) { get(it) }) +public fun Buffer.toShortArray(): ShortArray = when(this) { + is ShortBuffer -> array.copyOf() + else -> ShortArray(size, ::get) +} /** * Returns [ShortBuffer] over this array. From 401ca2443db984bb6fc56be9ce1f2761fb6e6000 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 12 Mar 2021 20:00:33 +0700 Subject: [PATCH 054/393] Provide pages workflow for sending Dokka artifacts to gh-pages --- .github/workflows/pages.yml | 31 +++++++++++++++++++++++++++++++ gradle.properties | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/pages.yml diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 000000000..29a2ed649 --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,31 @@ +name: Dokka publication + +on: + push: + branches: + - master + +jobs: + build: + runs-on: ubuntu-20.04 + steps: + - name: Checkout the repo + uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Cache gradle + uses: actions/cache@v2 + with: + path: ~/.gradle/caches + key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }} + restore-keys: | + ubuntu-20.04-gradle- + - name: Build + run: ./gradlew build --no-daemon --stacktrace + - name: Deploy to GitHub Pages + uses: JamesIves/github-pages-deploy-action@4.1.0 + with: + branch: gh-pages + folder: build/dokka/htmlMultiModule diff --git a/gradle.properties b/gradle.properties index aadc76c52..e28e22e8e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ kotlin.code.style=official kotlin.mpp.stability.nowarn=true kotlin.parallel.tasks.in.project=true org.gradle.configureondemand=true -org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m +org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G org.gradle.parallel=true kotlin.mpp.enableGranularSourceSetsMetadata=true From 52a942dbe24c9eb22fdbcd14a4038a04f2b03a98 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 12 Mar 2021 19:29:06 +0300 Subject: [PATCH 055/393] integrand --- .../kotlin/space/kscience/kmath/integration/Integrand.kt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt new file mode 100644 index 000000000..31006cde2 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt @@ -0,0 +1,9 @@ +package space.kscience.kmath.integration + +import kotlin.reflect.KClass + +public interface IntegrandFeature + +public interface Integrand { + public fun getFeature(type: KClass): T? = null +} \ No newline at end of file From 850dd3f58e371ac33b7c8193adae5cc2a9524afb Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 12 Mar 2021 20:00:33 +0700 Subject: [PATCH 056/393] Provide pages workflow for sending Dokka artifacts to gh-pages --- .github/workflows/pages.yml | 31 +++++++++++++++++++++++++++++++ gradle.properties | 10 ++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/pages.yml diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 000000000..29a2ed649 --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,31 @@ +name: Dokka publication + +on: + push: + branches: + - master + +jobs: + build: + runs-on: ubuntu-20.04 + steps: + - name: Checkout the repo + uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Cache gradle + uses: actions/cache@v2 + with: + path: ~/.gradle/caches + key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }} + restore-keys: | + ubuntu-20.04-gradle- + - name: Build + run: ./gradlew build --no-daemon --stacktrace + - name: Deploy to GitHub Pages + uses: JamesIves/github-pages-deploy-action@4.1.0 + with: + branch: gh-pages + folder: build/dokka/htmlMultiModule diff --git a/gradle.properties b/gradle.properties index 88b90f27b..e28e22e8e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,10 @@ kotlin.code.style=official -kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.mpp.stability.nowarn=true -kotlin.native.enableDependencyPropagation=false kotlin.parallel.tasks.in.project=true -org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m +org.gradle.configureondemand=true +org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G org.gradle.parallel=true -systemProp.org.gradle.internal.publish.checksums.insecure=true + +kotlin.mpp.enableGranularSourceSetsMetadata=true +kotlin.native.enableDependencyPropagation=false + From 1c02ab347127343ee9b81731d7f16b00da70372a Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 13 Mar 2021 00:04:10 +0700 Subject: [PATCH 057/393] Fix wrong task name --- .github/workflows/pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 29a2ed649..d6a6d97de 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -23,7 +23,7 @@ jobs: restore-keys: | ubuntu-20.04-gradle- - name: Build - run: ./gradlew build --no-daemon --stacktrace + run: ./gradlew dokkaHtmlMultiModule --no-daemon --stacktrace - name: Deploy to GitHub Pages uses: JamesIves/github-pages-deploy-action@4.1.0 with: From 756626c9bc8101f2c19c86f9af4cd8d92c35e2fb Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 13 Mar 2021 00:30:14 +0700 Subject: [PATCH 058/393] Fix Dokka build --- .github/workflows/pages.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index d6a6d97de..c70227fce 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -22,10 +22,17 @@ jobs: key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }} restore-keys: | ubuntu-20.04-gradle- + - name: Cache konan + uses: actions/cache@v2 + with: + path: ~/.konan + key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} + restore-keys: | + ${{ runner.os }}-gradle- - name: Build - run: ./gradlew dokkaHtmlMultiModule --no-daemon --stacktrace + run: ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace - name: Deploy to GitHub Pages uses: JamesIves/github-pages-deploy-action@4.1.0 with: - branch: gh-pages - folder: build/dokka/htmlMultiModule + branch: gh-pages + folder: build/dokka/htmlMultiModule From 171f5d5ba37aedf4fbe975c9c1c9791f5a078970 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 13 Mar 2021 00:57:40 +0700 Subject: [PATCH 059/393] Increase Metaspace size --- gradle.properties | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index e28e22e8e..4b3e4aa69 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,9 +2,8 @@ kotlin.code.style=official kotlin.mpp.stability.nowarn=true kotlin.parallel.tasks.in.project=true org.gradle.configureondemand=true -org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G +org.gradle.jvmargs=-XX:MaxMetaspaceSize=2G org.gradle.parallel=true kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.native.enableDependencyPropagation=false - From 6b44439d43b9cf25beba434ae42ffdf638b9f8be Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 13 Mar 2021 01:44:37 +0700 Subject: [PATCH 060/393] Fix lack of index.html --- .github/workflows/pages.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index c70227fce..82b0fb303 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -30,7 +30,9 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - name: Build - run: ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace + run: | + ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace + mv build/dokka/htmlMultiModule/-modules.html build/dokka/htmlMultiModule/index.html - name: Deploy to GitHub Pages uses: JamesIves/github-pages-deploy-action@4.1.0 with: From 9bc8e8fbf9ecfe3178e922f6a7ea23b92eaca207 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 12 Mar 2021 22:52:18 +0300 Subject: [PATCH 061/393] WIP vector space refactor --- .../kscience/kmath/benchmarks/DotBenchmark.kt | 26 +-- .../benchmarks/LinearAlgebraBenchmark.kt | 13 +- .../structures/StructureWriteBenchmark.kt | 2 +- .../kscience/kmath/commons/linear/CMMatrix.kt | 15 +- .../kscience/kmath/commons/linear/CMSolver.kt | 8 +- .../kscience/kmath/linear/BufferMatrix.kt | 144 ------------ .../kscience/kmath/linear/LinearAlgebra.kt | 8 +- .../kscience/kmath/linear/LinearSpace.kt | 213 ++++++++++++++++++ .../kscience/kmath/linear/LupDecomposition.kt | 35 ++- .../kscience/kmath/linear/MatrixBuilder.kt | 52 ++--- .../kscience/kmath/linear/MatrixContext.kt | 173 -------------- .../kscience/kmath/linear/MatrixWrapper.kt | 30 +-- ...ealMatrixContext.kt => RealLinearSpace.kt} | 23 +- .../kscience/kmath/linear/VectorSpace.kt | 72 ------ .../kscience/kmath/linear/VirtualMatrix.kt | 2 - .../space/kscience/kmath/nd/NDStructure.kt | 6 +- .../space/kscience/kmath/nd/Structure1D.kt | 6 +- .../space/kscience/kmath/nd/Structure2D.kt | 12 +- .../kmath/structures/BufferAccessor2D.kt | 2 +- .../space/kscience/kmath/linear/MatrixTest.kt | 6 +- .../kscience/kmath/linear/RealLUSolverTest.kt | 8 +- .../kscience/kmath/dimensions/Wrappers.kt | 8 +- ...jmlMatrixContext.kt => EjmlLinearSpace.kt} | 16 +- .../space/kscience/kmath/real/RealMatrix.kt | 34 +-- .../kaceince/kmath/real/RealVectorTest.kt | 4 +- 25 files changed, 352 insertions(+), 566 deletions(-) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/{RealMatrixContext.kt => RealLinearSpace.kt} (78%) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt rename kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/{EjmlMatrixContext.kt => EjmlLinearSpace.kt} (80%) diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt index 93b5c5549..8fb0c284e 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt @@ -4,11 +4,11 @@ import kotlinx.benchmark.Benchmark import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State -import space.kscience.kmath.commons.linear.CMMatrixContext -import space.kscience.kmath.ejml.EjmlMatrixContext -import space.kscience.kmath.linear.BufferMatrixContext +import space.kscience.kmath.commons.linear.CMLinearSpace +import space.kscience.kmath.ejml.EjmlLinearSpace +import space.kscience.kmath.linear.BufferLinearSpace import space.kscience.kmath.linear.Matrix -import space.kscience.kmath.linear.RealMatrixContext +import space.kscience.kmath.linear.RealLinearSpace import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer @@ -24,44 +24,44 @@ internal class DotBenchmark { val matrix1 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } val matrix2 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } - val cmMatrix1 = CMMatrixContext { matrix1.toCM() } - val cmMatrix2 = CMMatrixContext { matrix2.toCM() } + val cmMatrix1 = CMLinearSpace { matrix1.toCM() } + val cmMatrix2 = CMLinearSpace { matrix2.toCM() } - val ejmlMatrix1 = EjmlMatrixContext { matrix1.toEjml() } - val ejmlMatrix2 = EjmlMatrixContext { matrix2.toEjml() } + val ejmlMatrix1 = EjmlLinearSpace { matrix1.toEjml() } + val ejmlMatrix2 = EjmlLinearSpace { matrix2.toEjml() } } @Benchmark fun cmDot(blackhole: Blackhole) { - CMMatrixContext { + CMLinearSpace { blackhole.consume(cmMatrix1 dot cmMatrix2) } } @Benchmark fun ejmlDot(blackhole: Blackhole) { - EjmlMatrixContext { + EjmlLinearSpace { blackhole.consume(ejmlMatrix1 dot ejmlMatrix2) } } @Benchmark fun ejmlDotWithConversion(blackhole: Blackhole) { - EjmlMatrixContext { + EjmlLinearSpace { blackhole.consume(matrix1 dot matrix2) } } @Benchmark fun bufferedDot(blackhole: Blackhole) { - BufferMatrixContext(RealField, Buffer.Companion::real).invoke { + BufferLinearSpace(RealField, Buffer.Companion::real).invoke { blackhole.consume(matrix1 dot matrix2) } } @Benchmark fun realDot(blackhole: Blackhole) { - RealMatrixContext { + RealLinearSpace { blackhole.consume(matrix1 dot matrix2) } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt index 30cb6c0b9..85759d93c 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt @@ -4,13 +4,12 @@ import kotlinx.benchmark.Benchmark import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State -import space.kscience.kmath.commons.linear.CMMatrixContext -import space.kscience.kmath.commons.linear.CMMatrixContext.dot +import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.commons.linear.inverse -import space.kscience.kmath.ejml.EjmlMatrixContext +import space.kscience.kmath.ejml.EjmlLinearSpace import space.kscience.kmath.ejml.inverse +import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.Matrix -import space.kscience.kmath.linear.MatrixContext import space.kscience.kmath.linear.inverseWithLup import space.kscience.kmath.linear.real import kotlin.random.Random @@ -29,19 +28,19 @@ internal class LinearAlgebraBenchmark { @Benchmark fun kmathLupInversion(blackhole: Blackhole) { - blackhole.consume(MatrixContext.real.inverseWithLup(matrix)) + blackhole.consume(LinearSpace.real.inverseWithLup(matrix)) } @Benchmark fun cmLUPInversion(blackhole: Blackhole) { - with(CMMatrixContext) { + with(CMLinearSpace) { blackhole.consume(inverse(matrix)) } } @Benchmark fun ejmlInverse(blackhole: Blackhole) { - with(EjmlMatrixContext) { + with(EjmlLinearSpace) { blackhole.consume(inverse(matrix)) } } diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt index 13d6f00e4..66d85edff 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt @@ -7,7 +7,7 @@ import kotlin.system.measureTimeMillis @Suppress("UNUSED_VARIABLE") fun main() { val n = 6000 - val structure = NDStructure.build(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 } + val structure = NDStructure.buffered(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 } structure.mapToBuffer { it + 1 } // warm-up val time1 = measureTimeMillis { val res = structure.mapToBuffer { it + 1 } } println("Structure mapping finished in $time1 millis") diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index 393b28973..53f96626d 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -3,6 +3,7 @@ package space.kscience.kmath.commons.linear import org.apache.commons.math3.linear.* import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.RealField import space.kscience.kmath.structures.RealBuffer import kotlin.reflect.KClass import kotlin.reflect.cast @@ -55,7 +56,7 @@ public inline class CMMatrix(public val origin: RealMatrix) : Matrix { public fun RealMatrix.asMatrix(): CMMatrix = CMMatrix(this) -public class CMVector(public val origin: RealVector) : Point { +public class CMVector(public val origin: RealVector) : Vector { public override val size: Int get() = origin.dimension public override operator fun get(index: Int): Double = origin.getEntry(index) @@ -70,8 +71,8 @@ public fun Point.toCM(): CMVector = if (this is CMVector) this else { public fun RealVector.toPoint(): CMVector = CMVector(this) -public object CMMatrixContext : MatrixContext { - public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): CMMatrix { +public object CMLinearSpace : LinearSpace { + public override fun buildMatrix(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): CMMatrix { val array = Array(rows) { i -> DoubleArray(columns) { j -> initializer(i, j) } } return CMMatrix(Array2DRowRealMatrix(array)) } @@ -86,17 +87,15 @@ public object CMMatrixContext : MatrixContext { } } - override fun scale(a: Matrix, value: Double): Matrix = a.toCM().times(value) - public override fun Matrix.dot(other: Matrix): CMMatrix = CMMatrix(toCM().origin.multiply(other.toCM().origin)) - public override fun Matrix.dot(vector: Point): CMVector = + public override fun Matrix.dot(vector: Vector): CMVector = CMVector(toCM().origin.preMultiply(vector.toCM().origin)) public override operator fun Matrix.unaryMinus(): CMMatrix = - produce(rowNum, colNum) { i, j -> -get(i, j) } + buildMatrix(rowNum, colNum) { i, j -> -get(i, j) } public override fun add(a: Matrix, b: Matrix): CMMatrix = CMMatrix(a.toCM().origin.multiply(b.toCM().origin)) @@ -108,7 +107,7 @@ public object CMMatrixContext : MatrixContext { // CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble())) public override operator fun Matrix.times(value: Double): CMMatrix = - produce(rowNum, colNum) { i, j -> get(i, j) * value } + buildMatrix(rowNum, colNum) { i, j -> get(i, j) * value } } public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix = diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt index 3ce7ca9e6..ff4727aa2 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt @@ -12,7 +12,7 @@ public enum class CMDecomposition { CHOLESKY } -public fun CMMatrixContext.solver( +public fun CMLinearSpace.solver( a: Matrix, decomposition: CMDecomposition = CMDecomposition.LUP ): DecompositionSolver = when (decomposition) { @@ -23,19 +23,19 @@ public fun CMMatrixContext.solver( CMDecomposition.CHOLESKY -> CholeskyDecomposition(a.toCM().origin).solver } -public fun CMMatrixContext.solve( +public fun CMLinearSpace.solve( a: Matrix, b: Matrix, decomposition: CMDecomposition = CMDecomposition.LUP ): CMMatrix = solver(a, decomposition).solve(b.toCM().origin).asMatrix() -public fun CMMatrixContext.solve( +public fun CMLinearSpace.solve( a: Matrix, b: Point, decomposition: CMDecomposition = CMDecomposition.LUP ): CMVector = solver(a, decomposition).solve(b.toCM().origin).toPoint() -public fun CMMatrixContext.inverse( +public fun CMLinearSpace.inverse( a: Matrix, decomposition: CMDecomposition = CMDecomposition.LUP ): CMMatrix = solver(a, decomposition).inverse.asMatrix() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt deleted file mode 100644 index ba7b7358c..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferMatrix.kt +++ /dev/null @@ -1,144 +0,0 @@ -package space.kscience.kmath.linear - -import space.kscience.kmath.nd.NDStructure -import space.kscience.kmath.nd.Structure2D -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.invoke -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.asSequence - -/** - * Alias for [Structure2D] with more familiar name. - * - * @param T the type of items. - */ -public typealias Matrix = Structure2D - -/** - * Basic implementation of Matrix space based on [NDStructure] - */ -public class BufferMatrixContext( - public override val elementContext: A, - private val bufferFactory: BufferFactory, -) : GenericMatrixContext> where A : Ring, A : ScaleOperations { - - public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): BufferMatrix { - val buffer = bufferFactory(rows * columns) { offset -> initializer(offset / columns, offset % columns) } - return BufferMatrix(rows, columns, buffer) - } - - override fun scale(a: Matrix, value: Double): Matrix = elementContext { - produce(a.rowNum, a.colNum) { i, j -> - a[i, j] * value - } - } - - public override fun point(size: Int, initializer: (Int) -> T): Point = bufferFactory(size, initializer) - - private fun Matrix.toBufferMatrix(): BufferMatrix = if (this is BufferMatrix) this else { - produce(rowNum, colNum) { i, j -> get(i, j) } - } - - public fun one(rows: Int, columns: Int): Matrix = VirtualMatrix(rows, columns) { i, j -> - if (i == j) 1.0 else 0.0 - } + DiagonalFeature - - public override infix fun Matrix.dot(other: Matrix): BufferMatrix { - require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } - val bufferMatrix = toBufferMatrix() - val otherBufferMatrix = other.toBufferMatrix() - return elementContext { - produce(rowNum, other.colNum) { i, j -> - var res = one - for (l in 0 until colNum) { - res += bufferMatrix[i, l] * otherBufferMatrix[l, j] - } - res - } - } - } - - public override infix fun Matrix.dot(vector: Point): Point { - require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } - val bufferMatrix = toBufferMatrix() - return elementContext { - bufferFactory(rowNum) { i -> - var res = one - for (j in 0 until colNum) { - res += bufferMatrix[i, j] * vector[j] - } - res - } - } - } - - override fun add(a: Matrix, b: Matrix): BufferMatrix { - require(a.rowNum == b.rowNum) { "Row number mismatch in matrix addition. Left side: ${a.rowNum}, right side: ${b.rowNum}" } - require(a.colNum == b.colNum) { "Column number mismatch in matrix addition. Left side: ${a.colNum}, right side: ${b.colNum}" } - val aBufferMatrix = a.toBufferMatrix() - val bBufferMatrix = b.toBufferMatrix() - return elementContext { - produce(a.rowNum, a.colNum) { i, j -> - aBufferMatrix[i, j] + bBufferMatrix[i, j] - } - } - } - -// override fun multiply(a: Matrix, k: Number): BufferMatrix { -// val aBufferMatrix = a.toBufferMatrix() -// return elementContext { -// produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() } -// } -// } - - public companion object -} - -public class BufferMatrix( - public override val rowNum: Int, - public override val colNum: Int, - public val buffer: Buffer, -) : Matrix { - - init { - require(buffer.size == rowNum * colNum) { "Dimension mismatch for matrix structure" } - } - - override val shape: IntArray get() = intArrayOf(rowNum, colNum) - - public override operator fun get(index: IntArray): T = get(index[0], index[1]) - public override operator fun get(i: Int, j: Int): T = buffer[i * colNum + j] - - public override fun elements(): Sequence> = sequence { - for (i in 0 until rowNum) for (j in 0 until colNum) yield(intArrayOf(i, j) to get(i, j)) - } - - public override fun equals(other: Any?): Boolean { - if (this === other) return true - - return when (other) { - is NDStructure<*> -> NDStructure.contentEquals(this, other) - else -> false - } - } - - override fun hashCode(): Int { - var result = rowNum - result = 31 * result + colNum - result = 31 * result + buffer.hashCode() - return result - } - - public override fun toString(): String { - return if (rowNum <= 5 && colNum <= 5) - "Matrix(rowsNum = $rowNum, colNum = $colNum)\n" + - rows.asSequence().joinToString(prefix = "(", postfix = ")", separator = "\n ") { buffer -> - buffer.asSequence().joinToString(separator = "\t") { it.toString() } - } - else "Matrix(rowsNum = $rowNum, colNum = $colNum)" - } - - -} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearAlgebra.kt index ea871ccba..265a709e9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearAlgebra.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.linear +import space.kscience.kmath.nd.as1D import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.VirtualBuffer public typealias Point = Buffer @@ -10,16 +10,16 @@ public typealias Point = Buffer */ public interface LinearSolver { public fun solve(a: Matrix, b: Matrix): Matrix - public fun solve(a: Matrix, b: Point): Point = solve(a, b.asMatrix()).asPoint() + public fun solve(a: Matrix, b: Point): Point = solve(a, b.asMatrix()).asVector() public fun inverse(a: Matrix): Matrix } /** * Convert matrix to vector if it is possible */ -public fun Matrix.asPoint(): Point = +public fun Matrix.asVector(): Vector = if (this.colNum == 1) - VirtualBuffer(rowNum) { get(it, 0) } + as1D() else error("Can't convert matrix with more than one column to vector") diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt new file mode 100644 index 000000000..e0076cda9 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -0,0 +1,213 @@ +package space.kscience.kmath.linear + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.* +import space.kscience.kmath.operations.* +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferFactory +import kotlin.reflect.KClass + +/** + * Alias for [Structure2D] with more familiar name. + * + * @param T the type of items. + */ +public typealias Matrix = Structure2D + +/** + * Alias for [Structure1D] with more familiar name. + * + * @param T the type of items. + */ +public typealias Vector = Structure1D + +/** + * Basic operations on matrices and vectors. Operates on [Matrix]. + * + * @param T the type of items in the matrices. + * @param M the type of operated matrices. + */ +public interface LinearSpace> { + public val elementAlgebra: A + + /** + * Produces a matrix with this context and given dimensions. + */ + public fun buildMatrix(rows: Int, columns: Int, initializer: A.(i: Int, j: Int) -> T): Matrix + + /** + * Produces a point compatible with matrix space (and possibly optimized for it). + */ + public fun buildVector(size: Int, initializer: A.(Int) -> T): Vector = + buildMatrix(1, size) { _, j -> initializer(j) }.as1D() + + public operator fun Matrix.unaryMinus(): Matrix = buildMatrix(rowNum, colNum) { i, j -> + -get(i, j) + } + + public operator fun Vector.unaryMinus(): Vector = buildVector(size) { + -get(it) + } + + /** + * Matrix sum + */ + public operator fun Matrix.plus(other: Matrix): Matrix = buildMatrix(rowNum, colNum) { i, j -> + get(i, j) + other[i, j] + } + + + /** + * Vector sum + */ + public operator fun Vector.plus(other: Vector): Vector = buildVector(size) { + get(it) + other[it] + } + + /** + * Matrix subtraction + */ + public operator fun Matrix.minus(other: Matrix): Matrix = buildMatrix(rowNum, colNum) { i, j -> + get(i, j) - other[i, j] + } + + /** + * Vector subtraction + */ + public operator fun Vector.minus(other: Vector): Vector = buildVector(size) { + get(it) - other[it] + } + + + /** + * Computes the dot product of this matrix and another one. + * + * @receiver the multiplicand. + * @param other the multiplier. + * @return the dot product. + */ + public infix fun Matrix.dot(other: Matrix): Matrix { + require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } + return elementAlgebra { + buildMatrix(rowNum, other.colNum) { i, j -> + var res = zero + for (l in 0 until colNum) { + res += this@dot[i, l] * other[l, j] + } + res + } + } + } + + /** + * Computes the dot product of this matrix and a vector. + * + * @receiver the multiplicand. + * @param vector the multiplier. + * @return the dot product. + */ + public infix fun Matrix.dot(vector: Vector): Vector { + require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } + return elementAlgebra { + buildVector(rowNum) { i -> + var res = one + for (j in 0 until colNum) { + res += this@dot[i, j] * vector[j] + } + res + } + } + } + + /** + * Multiplies a matrix by its element. + * + * @receiver the multiplicand. + * @param value the multiplier. + * @receiver the product. + */ + public operator fun Matrix.times(value: T): Matrix = + buildMatrix(rowNum, colNum) { i, j -> get(i, j) * value } + + /** + * Multiplies an element by a matrix of it. + * + * @receiver the multiplicand. + * @param m the multiplier. + * @receiver the product. + */ + public operator fun T.times(m: Matrix): Matrix = m * this + + /** + * Multiplies a vector by its element. + * + * @receiver the multiplicand. + * @param value the multiplier. + * @receiver the product. + */ + public operator fun Vector.times(value: T): Vector = + buildVector(size) { i -> get(i) * value } + + /** + * Multiplies an element by a vector of it. + * + * @receiver the multiplicand. + * @param v the multiplier. + * @receiver the product. + */ + public operator fun T.times(v: Vector): Vector = v * this + + /** + * Gets a feature from the matrix. This function may return some additional features to + * [space.kscience.kmath.nd.NDStructure.getFeature]. + * + * @param F the type of feature. + * @param m the matrix. + * @param type the [KClass] instance of [F]. + * @return a feature object or `null` if it isn't present. + */ + @UnstableKMathAPI + public fun getFeature(m: Matrix, type: KClass): F? = m.getFeature(type) + + public companion object { + + /** + * A structured matrix with custom buffer + */ + public fun > buffered( + algebra: A, + bufferFactory: BufferFactory = Buffer.Companion::boxing, + ): LinearSpace = object : LinearSpace { + override val elementAlgebra: A = algebra + + override fun buildMatrix( + rows: Int, columns: Int, + initializer: A.(i: Int, j: Int) -> T, + ): Matrix = NDStructure.buffered(intArrayOf(rows, columns)) { (i, j) -> + algebra.initializer(i, j) + }.as2D() + + } + + /** + * Automatic buffered matrix, unboxed if it is possible + */ + public inline fun > auto(ring: A): LinearSpace = + buffered(ring, Buffer.Companion::auto) + } +} + +/** + * Gets a feature from the matrix. This function may return some additional features to + * [space.kscience.kmath.nd.NDStructure.getFeature]. + * + * @param T the type of items in the matrices. + * @param M the type of operated matrices. + * @param F the type of feature. + * @receiver the [LinearSpace] of [T]. + * @param m the matrix. + * @return a feature object or `null` if it isn't present. + */ +@UnstableKMathAPI +public inline fun LinearSpace.getFeature(m: Matrix): F? = getFeature(m, F::class) + diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt index a3d4cbc47..5d68534bc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt @@ -12,7 +12,7 @@ import space.kscience.kmath.structures.MutableBufferFactory * Common implementation of [LupDecompositionFeature]. */ public class LupDecomposition( - public val context: MatrixContext>, + public val context: LinearSpace, public val elementContext: Field, public val lu: Matrix, public val pivot: IntArray, @@ -62,15 +62,14 @@ public class LupDecomposition( } @PublishedApi -internal fun , F : Field> GenericMatrixContext.abs(value: T): T = - if (value > elementContext.zero) value else elementContext { -value } +internal fun > LinearSpace>.abs(value: T): T = + if (value > elementAlgebra.zero) value else elementAlgebra { -value } /** * Create a lup decomposition of generic matrix. */ -public fun > MatrixContext>.lup( +public fun > LinearSpace>.lup( factory: MutableBufferFactory, - elementContext: Field, matrix: Matrix, checkSingular: (T) -> Boolean, ): LupDecomposition { @@ -80,7 +79,7 @@ public fun > MatrixContext>.lup( //TODO just waits for KEEP-176 BufferAccessor2D(matrix.rowNum, matrix.colNum, factory).run { - elementContext { + elementAlgebra { val lu = create(matrix) // Initialize permutation array and parity @@ -142,18 +141,18 @@ public fun > MatrixContext>.lup( for (row in col + 1 until m) lu[row, col] /= luDiag } - return LupDecomposition(this@lup, elementContext, lu.collect(), pivot, even) + return LupDecomposition(this@lup, elementAlgebra, lu.collect(), pivot, even) } } } -public inline fun , F : Field> GenericMatrixContext>.lup( +public inline fun > LinearSpace>.lup( matrix: Matrix, noinline checkSingular: (T) -> Boolean, -): LupDecomposition = lup(MutableBuffer.Companion::auto, elementContext, matrix, checkSingular) +): LupDecomposition = lup(MutableBuffer.Companion::auto, matrix, checkSingular) -public fun MatrixContext>.lup(matrix: Matrix): LupDecomposition = - lup(Buffer.Companion::real, RealField, matrix) { it < 1e-11 } +public fun LinearSpace.lup(matrix: Matrix): LupDecomposition = + lup(Buffer.Companion::real, matrix) { it < 1e-11 } public fun LupDecomposition.solveWithLup( factory: MutableBufferFactory, @@ -198,7 +197,7 @@ public fun LupDecomposition.solveWithLup( } } - return context.produce(pivot.size, matrix.colNum) { i, j -> bp[i, j] } + return context.buildMatrix(pivot.size, matrix.colNum) { i, j -> bp[i, j] } } } } @@ -210,18 +209,18 @@ public inline fun LupDecomposition.solveWithLup(matrix: Mat * Solves a system of linear equations *ax = b** using LUP decomposition. */ @OptIn(UnstableKMathAPI::class) -public inline fun , F : Field> GenericMatrixContext>.solveWithLup( +public inline fun > LinearSpace>.solveWithLup( a: Matrix, b: Matrix, noinline bufferFactory: MutableBufferFactory = MutableBuffer.Companion::auto, noinline checkSingular: (T) -> Boolean, ): Matrix { // Use existing decomposition if it is provided by matrix - val decomposition = a.getFeature() ?: lup(bufferFactory, elementContext, a, checkSingular) + val decomposition = a.getFeature() ?: lup(bufferFactory, a, checkSingular) return decomposition.solveWithLup(bufferFactory, b) } -public inline fun , F : Field> GenericMatrixContext>.inverseWithLup( +public inline fun > LinearSpace>.inverseWithLup( matrix: Matrix, noinline bufferFactory: MutableBufferFactory = MutableBuffer.Companion::auto, noinline checkSingular: (T) -> Boolean, @@ -229,15 +228,15 @@ public inline fun , F : Field> GenericMatrixContext @OptIn(UnstableKMathAPI::class) -public fun RealMatrixContext.solveWithLup(a: Matrix, b: Matrix): Matrix { +public fun RealLinearSpace.solveWithLup(a: Matrix, b: Matrix): Matrix { // Use existing decomposition if it is provided by matrix val bufferFactory: MutableBufferFactory = MutableBuffer.Companion::real - val decomposition: LupDecomposition = a.getFeature() ?: lup(bufferFactory, RealField, a) { it < 1e-11 } + val decomposition: LupDecomposition = a.getFeature() ?: lup(bufferFactory, a) { it < 1e-11 } return decomposition.solveWithLup(bufferFactory, b) } /** * Inverses a square matrix using LUP decomposition. Non square matrix will throw a error. */ -public fun RealMatrixContext.inverseWithLup(matrix: Matrix): Matrix = +public fun RealLinearSpace.inverseWithLup(matrix: Matrix): Matrix = solveWithLup(matrix, one(matrix.rowNum, matrix.colNum)) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt index c96834360..57bea5cb6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt @@ -1,46 +1,30 @@ package space.kscience.kmath.linear -import space.kscience.kmath.nd.Structure2D -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Ring -public class MatrixBuilder(public val rows: Int, public val columns: Int) { - public operator fun invoke(vararg elements: T): Matrix { - require(rows * columns == elements.size) { "The number of elements ${elements.size} is not equal $rows * $columns" } - val buffer = elements.asBuffer() - return BufferMatrix(rows, columns, buffer) - } - //TODO add specific matrix builder functions like diagonal, etc +@UnstableKMathAPI +public fun LinearSpace>.matrix(rows: Int, columns: Int, vararg elements: T): Matrix { + require(rows * columns == elements.size) { "The number of elements ${elements.size} is not equal $rows * $columns" } + return buildMatrix(rows, columns) { i, j -> elements[i * columns + j] } } -public fun Structure2D.Companion.build(rows: Int, columns: Int): MatrixBuilder = MatrixBuilder(rows, columns) - -public fun Structure2D.Companion.row(vararg values: T): Matrix { - val buffer = values.asBuffer() - return BufferMatrix(1, values.size, buffer) +@UnstableKMathAPI +public fun LinearSpace>.vector(vararg elements: T): Vector { + return buildVector(elements.size, elements::get) } -public inline fun Structure2D.Companion.row( +public inline fun LinearSpace>.row( size: Int, - factory: BufferFactory = Buffer.Companion::auto, - noinline builder: (Int) -> T, -): Matrix { - val buffer = factory(size, builder) - return BufferMatrix(1, size, buffer) -} + crossinline builder: (Int) -> T, +): Matrix = buildMatrix(1, size) { _, j -> builder(j) } -public fun Structure2D.Companion.column(vararg values: T): Matrix { - val buffer = values.asBuffer() - return BufferMatrix(values.size, 1, buffer) -} +public fun LinearSpace>.row(vararg values: T): Matrix = row(values.size, values::get) -public inline fun Structure2D.Companion.column( +public inline fun LinearSpace>.column( size: Int, - factory: BufferFactory = Buffer.Companion::auto, - noinline builder: (Int) -> T, -): Matrix { - val buffer = factory(size, builder) - return BufferMatrix(size, 1, buffer) -} + crossinline builder: (Int) -> T, +): Matrix = buildMatrix(size, 1) { i, _ -> builder(i) } + +public fun LinearSpace>.column(vararg values: T): Matrix = column(values.size, values::get) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt deleted file mode 100644 index 6afec94e8..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixContext.kt +++ /dev/null @@ -1,173 +0,0 @@ -package space.kscience.kmath.linear - -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.* -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.asSequence -import kotlin.reflect.KClass - -/** - * Basic operations on matrices. Operates on [Matrix]. - * - * @param T the type of items in the matrices. - * @param M the type of operated matrices. - */ -public interface MatrixContext> : GroupOperations>, ScaleOperations> { - /** - * Produces a matrix with this context and given dimensions. - */ - public fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): M - - /** - * Produces a point compatible with matrix space (and possibly optimized for it). - */ - public fun point(size: Int, initializer: (Int) -> T): Point = Buffer.boxing(size, initializer) - - @Suppress("UNCHECKED_CAST") - public override fun binaryOperationFunction(operation: String): (left: Matrix, right: Matrix) -> M = - when (operation) { - "dot" -> { left, right -> left dot right } - else -> super.binaryOperationFunction(operation) as (Matrix, Matrix) -> M - } - - /** - * Computes the dot product of this matrix and another one. - * - * @receiver the multiplicand. - * @param other the multiplier. - * @return the dot product. - */ - public infix fun Matrix.dot(other: Matrix): M - - /** - * Computes the dot product of this matrix and a vector. - * - * @receiver the multiplicand. - * @param vector the multiplier. - * @return the dot product. - */ - public infix fun Matrix.dot(vector: Point): Point - - /** - * Multiplies a matrix by its element. - * - * @receiver the multiplicand. - * @param value the multiplier. - * @receiver the product. - */ - public operator fun Matrix.times(value: T): M - - /** - * Multiplies an element by a matrix of it. - * - * @receiver the multiplicand. - * @param m the multiplier. - * @receiver the product. - */ - public operator fun T.times(m: Matrix): M = m * this - - /** - * Gets a feature from the matrix. This function may return some additional features to - * [kscience.kmath.nd.NDStructure.getFeature]. - * - * @param F the type of feature. - * @param m the matrix. - * @param type the [KClass] instance of [F]. - * @return a feature object or `null` if it isn't present. - */ - @UnstableKMathAPI - public fun getFeature(m: Matrix, type: KClass): F? = m.getFeature(type) - - public companion object { - - /** - * A structured matrix with custom buffer - */ - public fun buffered( - ring: A, - bufferFactory: BufferFactory = Buffer.Companion::boxing, - ): GenericMatrixContext> where A : Ring, A: ScaleOperations = BufferMatrixContext(ring, bufferFactory) - - /** - * Automatic buffered matrix, unboxed if it is possible - */ - public inline fun auto(ring: A): GenericMatrixContext> where A : Ring, A: ScaleOperations = - buffered(ring, Buffer.Companion::auto) - } -} - -/** - * Gets a feature from the matrix. This function may return some additional features to - * [kscience.kmath.nd.NDStructure.getFeature]. - * - * @param T the type of items in the matrices. - * @param M the type of operated matrices. - * @param F the type of feature. - * @receiver the [MatrixContext] of [T]. - * @param m the matrix. - * @return a feature object or `null` if it isn't present. - */ -@UnstableKMathAPI -public inline fun MatrixContext.getFeature(m: Matrix): F? = - getFeature(m, F::class) - -/** - * Partial implementation of [MatrixContext] for matrices of [Ring]. - * - * @param T the type of items in the matrices. - * @param A the type of ring of matrix elements. - * @param M the type of operated matrices. - */ -public interface GenericMatrixContext> : MatrixContext where A : Ring, A : ScaleOperations{ - /** - * The ring over matrix elements. - */ - public val elementContext: A - - public override infix fun Matrix.dot(other: Matrix): M { - //TODO add typed error - require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } - - return produce(rowNum, other.colNum) { i, j -> - val row = rows[i] - val column = other.columns[j] - elementContext { sum(row.asSequence().zip(column.asSequence(), ::multiply)) } - } - } - - public override infix fun Matrix.dot(vector: Point): Point { - //TODO add typed error - require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } - - return point(rowNum) { i -> - val row = rows[i] - elementContext { sum(row.asSequence().zip(vector.asSequence(), ::multiply)) } - } - } - - public override operator fun Matrix.unaryMinus(): M = - produce(rowNum, colNum) { i, j -> elementContext { -get(i, j) } } - - public override fun add(a: Matrix, b: Matrix): M { - require(a.rowNum == b.rowNum && a.colNum == b.colNum) { - "Matrix operation dimension mismatch. [${a.rowNum},${a.colNum}] + [${b.rowNum},${b.colNum}]" - } - - return produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] + b[i, j] } } - } - - public override operator fun Matrix.minus(b: Matrix): M { - require(rowNum == b.rowNum && colNum == b.colNum) { - "Matrix operation dimension mismatch. [$rowNum,$colNum] - [${b.rowNum},${b.colNum}]" - } - - return produce(rowNum, colNum) { i, j -> elementContext { get(i, j) + b[i, j] } } - } -// -// public override fun multiply(a: Matrix, k: Number): M = -// produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] * k } } - - public override operator fun Matrix.times(value: T): M = - produce(rowNum, colNum) { i, j -> elementContext { get(i, j) * value } } -} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt index 69e4a916f..97f0acd61 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt @@ -1,14 +1,9 @@ package space.kscience.kmath.linear import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.getFeature import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.structures.asBuffer -import kotlin.math.sqrt import kotlin.reflect.KClass -import kotlin.reflect.safeCast /** * A [Matrix] that holds [MatrixFeature] objects. @@ -24,7 +19,8 @@ public class MatrixWrapper internal constructor( * Get the first feature matching given class. Does not guarantee that matrix has only one feature matching the criteria */ @UnstableKMathAPI - override fun getFeature(type: KClass): T? = type.safeCast(features.find { type.isInstance(it) }) + @Suppress("UNCHECKED_CAST") + override fun getFeature(type: KClass): T? = features.singleOrNull { type.isInstance(it) } as? T ?: origin.getFeature(type) override fun equals(other: Any?): Boolean = origin == other @@ -61,35 +57,25 @@ public operator fun Matrix.plus(newFeatures: Collection Structure2D.Companion.square(vararg elements: T): Matrix { - val size: Int = sqrt(elements.size.toDouble()).toInt() - require(size * size == elements.size) { "The number of elements ${elements.size} is not a full square" } - val buffer = elements.asBuffer() - return BufferMatrix(size, size, buffer) -} - /** * Diagonal matrix of ones. The matrix is virtual no actual matrix is created */ -public fun GenericMatrixContext.one( +public fun LinearSpace>.one( rows: Int, columns: Int, -): Matrix where A : Ring, A : ScaleOperations = VirtualMatrix(rows, columns) { i, j -> - if (i == j) elementContext.one else elementContext.zero +): Matrix = VirtualMatrix(rows, columns) { i, j -> + if (i == j) elementAlgebra.one else elementAlgebra.zero } + UnitFeature /** * A virtual matrix of zeroes */ -public fun GenericMatrixContext.zero( +public fun LinearSpace>.zero( rows: Int, columns: Int, -): Matrix where A : Ring, A : ScaleOperations = VirtualMatrix(rows, columns) { _, _ -> - elementContext.zero +): Matrix = VirtualMatrix(rows, columns) { _, _ -> + elementAlgebra.zero } + ZeroFeature public class TransposedFeature(public val original: Matrix) : MatrixFeature diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealLinearSpace.kt similarity index 78% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealLinearSpace.kt index dbccb7536..6dc97c51e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealMatrixContext.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealLinearSpace.kt @@ -1,34 +1,37 @@ package space.kscience.kmath.linear +import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.structures.RealBuffer -public object RealMatrixContext : MatrixContext>, ScaleOperations> { +public object RealLinearSpace : LinearSpace, ScaleOperations> { - public override fun produce( + override val elementAlgebra: RealField get() = RealField + + public override fun buildMatrix( rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double, - ): BufferMatrix { + ): Matrix { val buffer = RealBuffer(rows * columns) { offset -> initializer(offset / columns, offset % columns) } - return BufferMatrix(rows, columns, buffer) + return BufferMatrix(rows, columns, buffer) } public fun Matrix.toBufferMatrix(): BufferMatrix = if (this is BufferMatrix) this else { - produce(rowNum, colNum) { i, j -> get(i, j) } + buildMatrix(rowNum, colNum) { i, j -> get(i, j) } } public fun one(rows: Int, columns: Int): Matrix = VirtualMatrix(rows, columns) { i, j -> if (i == j) 1.0 else 0.0 } + DiagonalFeature - override fun Matrix.unaryMinus(): Matrix = produce(rowNum, colNum) { i, j -> -get(i, j) } + override fun Matrix.unaryMinus(): Matrix = buildMatrix(rowNum, colNum) { i, j -> -get(i, j) } public override infix fun Matrix.dot(other: Matrix): BufferMatrix { require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } val bufferMatrix = toBufferMatrix() val otherBufferMatrix = other.toBufferMatrix() - return produce(rowNum, other.colNum) { i, j -> + return buildMatrix(rowNum, other.colNum) { i, j -> var res = 0.0 for (l in 0 until colNum) { res += bufferMatrix[i, l] * otherBufferMatrix[l, j] @@ -54,14 +57,14 @@ public object RealMatrixContext : MatrixContext>, S require(a.colNum == b.colNum) { "Column number mismatch in matrix addition. Left side: ${a.colNum}, right side: ${b.colNum}" } val aBufferMatrix = a.toBufferMatrix() val bBufferMatrix = b.toBufferMatrix() - return produce(a.rowNum, a.colNum) { i, j -> + return buildMatrix(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] + bBufferMatrix[i, j] } } override fun scale(a: Matrix, value: Double): BufferMatrix { val bufferMatrix = a.toBufferMatrix() - return produce(a.rowNum, a.colNum) { i, j -> bufferMatrix[i, j] * value } + return buildMatrix(a.rowNum, a.colNum) { i, j -> bufferMatrix[i, j] * value } } override fun Matrix.times(value: Double): BufferMatrix = scale(this, value) @@ -82,4 +85,4 @@ public object RealMatrixContext : MatrixContext>, S /** * Partially optimized real-valued matrix */ -public val MatrixContext.Companion.real: RealMatrixContext get() = RealMatrixContext +public val LinearSpace.Companion.real: RealLinearSpace get() = RealLinearSpace diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt deleted file mode 100644 index cfacf6826..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VectorSpace.kt +++ /dev/null @@ -1,72 +0,0 @@ -package space.kscience.kmath.linear - -import space.kscience.kmath.operations.Group -import space.kscience.kmath.operations.RealField -import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.invoke -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory - -/** - * A linear space for vectors. - * Could be used on any point-like structure - */ -public interface VectorSpace : Group>, ScaleOperations> - where A : Group, A : ScaleOperations { - public val size: Int - public val algebra: A - override val zero: Point get() = produce { algebra.zero } - - public fun produce(initializer: A.(Int) -> T): Point - - override fun add(a: Point, b: Point): Point = produce { algebra { a[it] + b[it] } } - - override fun scale(a: Point, value: Double): Point = produce { algebra.scale(a[it], value) } - - override fun Point.unaryMinus(): Point = produce { -get(it) } - - //TODO add basis - - public companion object { - private val realSpaceCache: MutableMap> = hashMapOf() - - /** - * Non-boxing double vector space - */ - public fun real(size: Int): BufferVectorSpace = realSpaceCache.getOrPut(size) { - BufferVectorSpace( - size, - RealField, - Buffer.Companion::auto - ) - } - - /** - * A structured vector space with custom buffer - */ - public fun buffered( - size: Int, - space: A, - bufferFactory: BufferFactory = Buffer.Companion::boxing, - ): BufferVectorSpace where A : Group, A : ScaleOperations = - BufferVectorSpace(size, space, bufferFactory) - - /** - * Automatic buffered vector, unboxed if it is possible - */ - public inline fun auto( - size: Int, - space: A, - ): VectorSpace where A : Group, A : ScaleOperations = - buffered(size, space, Buffer.Companion::auto) - } -} - - -public class BufferVectorSpace( - override val size: Int, - override val algebra: A, - public val bufferFactory: BufferFactory, -) : VectorSpace where A : Group, A : ScaleOperations { - override fun produce(initializer: A.(Int) -> T): Buffer = bufferFactory(size) { algebra.initializer(it) } -} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt index 26b1899a1..11699ce2f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt @@ -31,6 +31,4 @@ public class VirtualMatrix( result = 31 * result + generator.hashCode() return result } - - } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt index 137772632..62e126694 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt @@ -74,7 +74,7 @@ public interface NDStructure { * * Strides should be reused if possible. */ - public fun build( + public fun buffered( strides: Strides, bufferFactory: BufferFactory = Buffer.Companion::boxing, initializer: (IntArray) -> T, @@ -94,11 +94,11 @@ public interface NDStructure { crossinline initializer: (IntArray) -> T, ): NDBuffer = NDBuffer(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) }) - public fun build( + public fun buffered( shape: IntArray, bufferFactory: BufferFactory = Buffer.Companion::boxing, initializer: (IntArray) -> T, - ): NDBuffer = build(DefaultStrides(shape), bufferFactory, initializer) + ): NDBuffer = buffered(DefaultStrides(shape), bufferFactory, initializer) public inline fun auto( shape: IntArray, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index e83485ff0..c54bfeed9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -46,7 +46,11 @@ private inline class Buffer1DWrapper(val buffer: Buffer) : Structure1D * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch */ public fun NDStructure.as1D(): Structure1D = if (shape.size == 1) { - if (this is NDBuffer) Buffer1DWrapper(this.buffer) else Structure1DWrapper(this) + when (this) { + is Structure1DWrapper -> this + is NDBuffer -> Buffer1DWrapper(this.buffer) + else -> Structure1DWrapper(this) + } } else error("Can't create 1d-structure from ${shape.size}d-structure") diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index fcc8c0d7e..0098eeb3b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -1,7 +1,5 @@ package space.kscience.kmath.nd -import space.kscience.kmath.linear.BufferMatrix -import space.kscience.kmath.linear.RealMatrixContext import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.VirtualBuffer @@ -54,15 +52,7 @@ public interface Structure2D : NDStructure { for (j in 0 until colNum) yield(intArrayOf(i, j) to get(i, j)) } - public companion object { - public inline fun real( - rows: Int, - columns: Int, - crossinline init: (i: Int, j: Int) -> Double, - ): BufferMatrix = RealMatrixContext.produce(rows,columns) { i, j -> - init(i, j) - } - } + public companion object } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt index fd440a344..d9e37ebd8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt @@ -25,7 +25,7 @@ internal class BufferAccessor2D( public fun create(mat: Structure2D): MutableBuffer = create { i, j -> mat[i, j] } //TODO optimize wrapper - public fun MutableBuffer.collect(): Structure2D = NDStructure.build( + public fun MutableBuffer.collect(): Structure2D = NDStructure.buffered( DefaultStrides(intArrayOf(rowNum, colNum)), factory ) { (i, j) -> diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt index 75967f024..5cf83889a 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt @@ -10,7 +10,7 @@ import kotlin.test.assertEquals class MatrixTest { @Test fun testTranspose() { - val matrix = MatrixContext.real.one(3, 3) + val matrix = LinearSpace.real.one(3, 3) val transposed = matrix.transpose() assertEquals(matrix, transposed) } @@ -39,7 +39,7 @@ class MatrixTest { infix fun Matrix.pow(power: Int): Matrix { var res = this repeat(power - 1) { - res = RealMatrixContext.invoke { res dot this@pow } + res = RealLinearSpace.invoke { res dot this@pow } } return res } @@ -52,7 +52,7 @@ class MatrixTest { val firstMatrix = NDStructure.auto(2, 3) { (i, j) -> (i + j).toDouble() }.as2D() val secondMatrix = NDStructure.auto(3, 2) { (i, j) -> (i + j).toDouble() }.as2D() - MatrixContext.real.run { + LinearSpace.real.run { // val firstMatrix = produce(2, 3) { i, j -> (i + j).toDouble() } // val secondMatrix = produce(3, 2) { i, j -> (i + j).toDouble() } val result = firstMatrix dot secondMatrix diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt index f1289801a..4d6b8f5be 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt @@ -7,8 +7,8 @@ class RealLUSolverTest { @Test fun testInvertOne() { - val matrix = MatrixContext.real.one(2, 2) - val inverted = MatrixContext.real.inverseWithLup(matrix) + val matrix = LinearSpace.real.one(2, 2) + val inverted = LinearSpace.real.inverseWithLup(matrix) assertEquals(matrix, inverted) } @@ -19,7 +19,7 @@ class RealLUSolverTest { 1.0, 3.0 ) - MatrixContext.real.run { + LinearSpace.real.run { val lup = lup(matrix) //Check determinant @@ -36,7 +36,7 @@ class RealLUSolverTest { 1.0, 3.0 ) - val inverted = MatrixContext.real.inverseWithLup(matrix) + val inverted = LinearSpace.real.inverseWithLup(matrix) val expected = Matrix.square( 0.375, -0.125, diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt index 237824a39..89ff97f14 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt @@ -77,7 +77,7 @@ public inline class DPointWrapper(public val point: Point) /** * Basic operations on dimension-safe matrices. Operates on [Matrix] */ -public inline class DMatrixContext(public val context: MatrixContext>) { +public inline class DMatrixContext(public val context: LinearSpace>) { public inline fun Matrix.coerce(): DMatrix { require(rowNum == Dimension.dim().toInt()) { "Row number mismatch: expected ${Dimension.dim()} but found $rowNum" @@ -96,14 +96,14 @@ public inline class DMatrixContext(public val context: MatrixContext produce(noinline initializer: (i: Int, j: Int) -> T): DMatrix { val rows = Dimension.dim() val cols = Dimension.dim() - return context.produce(rows.toInt(), cols.toInt(), initializer).coerce() + return context.buildMatrix(rows.toInt(), cols.toInt(), initializer).coerce() } public inline fun point(noinline initializer: (Int) -> T): DPoint { val size = Dimension.dim() return DPoint.coerceUnsafe( - context.point( + context.buildVector( size.toInt(), initializer ) @@ -136,7 +136,7 @@ public inline class DMatrixContext(public val context: MatrixContext).transpose() }.coerce() public companion object { - public val real: DMatrixContext = DMatrixContext(MatrixContext.real) + public val real: DMatrixContext = DMatrixContext(LinearSpace.real) } } diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrixContext.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt similarity index 80% rename from kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrixContext.kt rename to kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index 95c465975..c3f93ca55 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrixContext.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -11,7 +11,7 @@ import space.kscience.kmath.operations.ScaleOperations * * @author Iaroslav Postovalov */ -public object EjmlMatrixContext : MatrixContext, ScaleOperations> { +public object EjmlLinearSpace : LinearSpace, ScaleOperations> { /** * Converts this matrix to EJML one. @@ -19,7 +19,7 @@ public object EjmlMatrixContext : MatrixContext, ScaleOperat @OptIn(UnstableKMathAPI::class) public fun Matrix.toEjml(): EjmlMatrix = when (val matrix = origin) { is EjmlMatrix -> matrix - else -> produce(rowNum, colNum) { i, j -> get(i, j) } + else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } } /** @@ -30,14 +30,14 @@ public object EjmlMatrixContext : MatrixContext, ScaleOperat (0 until it.numRows()).forEach { row -> it[row, 0] = get(row) } }) - override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): EjmlMatrix = + override fun buildMatrix(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): EjmlMatrix = EjmlMatrix(SimpleMatrix(rows, columns).also { (0 until rows).forEach { row -> (0 until columns).forEach { col -> it[row, col] = initializer(row, col) } } }) - override fun point(size: Int, initializer: (Int) -> Double): Point = + override fun buildVector(size: Int, initializer: (Int) -> Double): Point = EjmlVector(SimpleMatrix(size, 1).also { (0 until it.numRows()).forEach { row -> it[row, 0] = initializer(row) } }) @@ -58,7 +58,7 @@ public object EjmlMatrixContext : MatrixContext, ScaleOperat EjmlMatrix(toEjml().origin - b.toEjml().origin) public override fun scale(a: Matrix, value: Double): EjmlMatrix = - produce(a.rowNum, a.colNum) { i, j -> a[i, j] * value } + buildMatrix(a.rowNum, a.colNum) { i, j -> a[i, j] * value } public override operator fun Matrix.times(value: Double): EjmlMatrix = EjmlMatrix(toEjml().origin.scale(value)) @@ -72,7 +72,7 @@ public object EjmlMatrixContext : MatrixContext, ScaleOperat * @return the solution for 'x' that is n by p. * @author Iaroslav Postovalov */ -public fun EjmlMatrixContext.solve(a: Matrix, b: Matrix): EjmlMatrix = +public fun EjmlLinearSpace.solve(a: Matrix, b: Matrix): EjmlMatrix = EjmlMatrix(a.toEjml().origin.solve(b.toEjml().origin)) /** @@ -83,10 +83,10 @@ public fun EjmlMatrixContext.solve(a: Matrix, b: Matrix): EjmlMa * @return the solution for 'x' that is n by p. * @author Iaroslav Postovalov */ -public fun EjmlMatrixContext.solve(a: Matrix, b: Point): EjmlVector = +public fun EjmlLinearSpace.solve(a: Matrix, b: Point): EjmlVector = EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) @OptIn(UnstableKMathAPI::class) public fun EjmlMatrix.inverted(): EjmlMatrix = getFeature>()!!.inverse as EjmlMatrix -public fun EjmlMatrixContext.inverse(matrix: Matrix): Matrix = matrix.toEjml().inverted() \ No newline at end of file +public fun EjmlLinearSpace.inverse(matrix: Matrix): Matrix = matrix.toEjml().inverted() \ No newline at end of file diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt index 30d002498..b93c430f9 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt @@ -22,14 +22,14 @@ import kotlin.math.pow public typealias RealMatrix = Matrix public fun realMatrix(rowNum: Int, colNum: Int, initializer: (i: Int, j: Int) -> Double): RealMatrix = - MatrixContext.real.produce(rowNum, colNum, initializer) + LinearSpace.real.buildMatrix(rowNum, colNum, initializer) public fun Array.toMatrix(): RealMatrix { - return MatrixContext.real.produce(size, this[0].size) { row, col -> this[row][col] } + return LinearSpace.real.buildMatrix(size, this[0].size) { row, col -> this[row][col] } } public fun Sequence.toMatrix(): RealMatrix = toList().let { - MatrixContext.real.produce(it.size, it[0].size) { row, col -> it[row][col] } + LinearSpace.real.buildMatrix(it.size, it[0].size) { row, col -> it[row][col] } } public fun RealMatrix.repeatStackVertical(n: Int): RealMatrix = @@ -42,37 +42,37 @@ public fun RealMatrix.repeatStackVertical(n: Int): RealMatrix = */ public operator fun RealMatrix.times(double: Double): RealMatrix = - MatrixContext.real.produce(rowNum, colNum) { row, col -> + LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> this[row, col] * double } public operator fun RealMatrix.plus(double: Double): RealMatrix = - MatrixContext.real.produce(rowNum, colNum) { row, col -> + LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> this[row, col] + double } public operator fun RealMatrix.minus(double: Double): RealMatrix = - MatrixContext.real.produce(rowNum, colNum) { row, col -> + LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> this[row, col] - double } public operator fun RealMatrix.div(double: Double): RealMatrix = - MatrixContext.real.produce(rowNum, colNum) { row, col -> + LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> this[row, col] / double } public operator fun Double.times(matrix: RealMatrix): RealMatrix = - MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col -> + LinearSpace.real.buildMatrix(matrix.rowNum, matrix.colNum) { row, col -> this * matrix[row, col] } public operator fun Double.plus(matrix: RealMatrix): RealMatrix = - MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col -> + LinearSpace.real.buildMatrix(matrix.rowNum, matrix.colNum) { row, col -> this + matrix[row, col] } public operator fun Double.minus(matrix: RealMatrix): RealMatrix = - MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col -> + LinearSpace.real.buildMatrix(matrix.rowNum, matrix.colNum) { row, col -> this - matrix[row, col] } @@ -87,20 +87,20 @@ public operator fun Double.minus(matrix: RealMatrix): RealMatrix = @UnstableKMathAPI public operator fun RealMatrix.times(other: RealMatrix): RealMatrix = - MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] * other[row, col] } + LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> this[row, col] * other[row, col] } public operator fun RealMatrix.plus(other: RealMatrix): RealMatrix = - MatrixContext.real.add(this, other) + LinearSpace.real.add(this, other) public operator fun RealMatrix.minus(other: RealMatrix): RealMatrix = - MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] - other[row, col] } + LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> this[row, col] - other[row, col] } /* * Operations on columns */ public inline fun RealMatrix.appendColumn(crossinline mapper: (Buffer) -> Double): RealMatrix = - MatrixContext.real.produce(rowNum, colNum + 1) { row, col -> + LinearSpace.real.buildMatrix(rowNum, colNum + 1) { row, col -> if (col < colNum) this[row, col] else @@ -108,7 +108,7 @@ public inline fun RealMatrix.appendColumn(crossinline mapper: (Buffer) - } public fun RealMatrix.extractColumns(columnRange: IntRange): RealMatrix = - MatrixContext.real.produce(rowNum, columnRange.count()) { row, col -> + LinearSpace.real.buildMatrix(rowNum, columnRange.count()) { row, col -> this[row, columnRange.first + col] } @@ -141,14 +141,14 @@ public fun RealMatrix.max(): Double? = elements().map { (_, value) -> value }.ma public fun RealMatrix.average(): Double = elements().map { (_, value) -> value }.average() public inline fun RealMatrix.map(crossinline transform: (Double) -> Double): RealMatrix = - MatrixContext.real.produce(rowNum, colNum) { i, j -> + LinearSpace.real.buildMatrix(rowNum, colNum) { i, j -> transform(get(i, j)) } /** * Inverse a square real matrix using LUP decomposition */ -public fun RealMatrix.inverseWithLup(): RealMatrix = MatrixContext.real.inverseWithLup(this) +public fun RealMatrix.inverseWithLup(): RealMatrix = LinearSpace.real.inverseWithLup(this) //extended operations diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt index 463c68681..5d032de67 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt @@ -1,6 +1,6 @@ package kaceince.kmath.real -import space.kscience.kmath.linear.MatrixContext +import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.asMatrix import space.kscience.kmath.linear.real import space.kscience.kmath.linear.transpose @@ -32,7 +32,7 @@ internal class RealVectorTest { val vector2 = Buffer.real(5) { 5 - it.toDouble() } val matrix1 = vector1.asMatrix() val matrix2 = vector2.asMatrix().transpose() - val product = MatrixContext.real { matrix1 dot matrix2 } + val product = LinearSpace.real { matrix1 dot matrix2 } assertEquals(5.0, product[1, 0]) assertEquals(6.0, product[2, 2]) } From 19d3998c3b4c636692a1690c27cb46b40169f50c Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 13 Mar 2021 10:10:00 +0300 Subject: [PATCH 062/393] WIP vector space refactor --- .../kscience/kmath/commons/linear/CMMatrix.kt | 80 ++++++--- .../kscience/kmath/linear/LinearSpace.kt | 12 +- .../kscience/kmath/linear/MatrixBuilder.kt | 2 +- .../kscience/kmath/linear/RealLinearSpace.kt | 156 +++++++++--------- .../space/kscience/kmath/nd/NDStructure.kt | 2 +- .../kscience/kmath/ejml/EjmlLinearSpace.kt | 62 +++++-- .../space/kscience/kmath/ejml/EjmlMatrix.kt | 2 +- 7 files changed, 185 insertions(+), 131 deletions(-) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index 53f96626d..c1c3d716a 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -3,12 +3,13 @@ package space.kscience.kmath.commons.linear import org.apache.commons.math3.linear.* import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.NDStructure import space.kscience.kmath.operations.RealField import space.kscience.kmath.structures.RealBuffer import kotlin.reflect.KClass import kotlin.reflect.cast -public inline class CMMatrix(public val origin: RealMatrix) : Matrix { +public class CMMatrix(public val origin: RealMatrix) : Matrix { public override val rowNum: Int get() = origin.rowDimension public override val colNum: Int get() = origin.columnDimension @@ -51,12 +52,17 @@ public inline class CMMatrix(public val origin: RealMatrix) : Matrix { }?.let(type::cast) public override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is NDStructure<*>) return false + return NDStructure.contentEquals(this, other) + } + + override fun hashCode(): Int = origin.hashCode() } - -public fun RealMatrix.asMatrix(): CMMatrix = CMMatrix(this) - -public class CMVector(public val origin: RealVector) : Vector { +public inline class CMVector(public val origin: RealVector) : Vector { public override val size: Int get() = origin.dimension public override operator fun get(index: Int): Double = origin.getEntry(index) @@ -64,16 +70,17 @@ public class CMVector(public val origin: RealVector) : Vector { public override operator fun iterator(): Iterator = origin.toArray().iterator() } -public fun Point.toCM(): CMVector = if (this is CMVector) this else { - val array = DoubleArray(size) { this[it] } - CMVector(ArrayRealVector(array)) -} - public fun RealVector.toPoint(): CMVector = CMVector(this) public object CMLinearSpace : LinearSpace { - public override fun buildMatrix(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): CMMatrix { - val array = Array(rows) { i -> DoubleArray(columns) { j -> initializer(i, j) } } + override val elementAlgebra: RealField get() = RealField + + public override fun buildMatrix( + rows: Int, + columns: Int, + initializer: RealField.(i: Int, j: Int) -> Double, + ): CMMatrix { + val array = Array(rows) { i -> DoubleArray(columns) { j -> RealField.initializer(i, j) } } return CMMatrix(Array2DRowRealMatrix(array)) } @@ -83,31 +90,50 @@ public object CMLinearSpace : LinearSpace { else -> { //TODO add feature analysis val array = Array(rowNum) { i -> DoubleArray(colNum) { j -> get(i, j) } } - CMMatrix(Array2DRowRealMatrix(array)) + Array2DRowRealMatrix(array).wrap() } } + public fun Vector.toCM(): CMVector = if (this is CMVector) this else { + val array = DoubleArray(size) { this[it] } + ArrayRealVector(array).wrap() + } + + private fun RealMatrix.wrap(): CMMatrix = CMMatrix(this) + private fun RealVector.wrap(): CMVector = CMVector(this) + + override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Vector = + ArrayRealVector(DoubleArray(size) { RealField.initializer(it) }).wrap() + + override fun Matrix.plus(other: Matrix): CMMatrix = + toCM().origin.add(other.toCM().origin).wrap() + + override fun Vector.plus(other: Vector): CMVector = + toCM().origin.add(other.toCM().origin).wrap() + + override fun Vector.minus(other: Vector): CMVector = + toCM().origin.subtract(other.toCM().origin).wrap() public override fun Matrix.dot(other: Matrix): CMMatrix = - CMMatrix(toCM().origin.multiply(other.toCM().origin)) + toCM().origin.multiply(other.toCM().origin).wrap() public override fun Matrix.dot(vector: Vector): CMVector = - CMVector(toCM().origin.preMultiply(vector.toCM().origin)) + toCM().origin.preMultiply(vector.toCM().origin).wrap() - public override operator fun Matrix.unaryMinus(): CMMatrix = - buildMatrix(rowNum, colNum) { i, j -> -get(i, j) } - - public override fun add(a: Matrix, b: Matrix): CMMatrix = - CMMatrix(a.toCM().origin.multiply(b.toCM().origin)) - - public override operator fun Matrix.minus(b: Matrix): CMMatrix = - CMMatrix(toCM().origin.subtract(b.toCM().origin)) - -// public override fun multiply(a: Matrix, k: Number): CMMatrix = -// CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble())) + public override operator fun Matrix.minus(other: Matrix): CMMatrix = + toCM().origin.subtract(other.toCM().origin).wrap() public override operator fun Matrix.times(value: Double): CMMatrix = - buildMatrix(rowNum, colNum) { i, j -> get(i, j) * value } + toCM().origin.scalarMultiply(value).wrap() + + override fun Double.times(m: Matrix): CMMatrix = + m * this + + override fun Vector.times(value: Double): CMVector = + toCM().origin.mapMultiply(value).wrap() + + override fun Double.times(v: Vector): CMVector = + v * this } public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index e0076cda9..5800bdd0d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -14,12 +14,7 @@ import kotlin.reflect.KClass */ public typealias Matrix = Structure2D -/** - * Alias for [Structure1D] with more familiar name. - * - * @param T the type of items. - */ -public typealias Vector = Structure1D +public typealias Vector = Point /** * Basic operations on matrices and vectors. Operates on [Matrix]. @@ -183,12 +178,13 @@ public interface LinearSpace> { override fun buildMatrix( rows: Int, columns: Int, initializer: A.(i: Int, j: Int) -> T, - ): Matrix = NDStructure.buffered(intArrayOf(rows, columns)) { (i, j) -> + ): Matrix = NDStructure.buffered(intArrayOf(rows, columns), bufferFactory) { (i, j) -> algebra.initializer(i, j) }.as2D() - } + public val real: LinearSpace = buffered(RealField, Buffer.Companion::real) + /** * Automatic buffered matrix, unboxed if it is possible */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt index 57bea5cb6..28df78dad 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt @@ -12,7 +12,7 @@ public fun LinearSpace>.matrix(rows: Int, columns: Int, var @UnstableKMathAPI public fun LinearSpace>.vector(vararg elements: T): Vector { - return buildVector(elements.size, elements::get) + return buildVector(elements.size) { elements[it] } } public inline fun LinearSpace>.row( diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealLinearSpace.kt index 6dc97c51e..3fa23db82 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealLinearSpace.kt @@ -1,88 +1,86 @@ package space.kscience.kmath.linear -import space.kscience.kmath.operations.RealField -import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.structures.RealBuffer - -public object RealLinearSpace : LinearSpace, ScaleOperations> { - - override val elementAlgebra: RealField get() = RealField - - public override fun buildMatrix( - rows: Int, - columns: Int, - initializer: (i: Int, j: Int) -> Double, - ): Matrix { - val buffer = RealBuffer(rows * columns) { offset -> initializer(offset / columns, offset % columns) } - return BufferMatrix(rows, columns, buffer) - } - - public fun Matrix.toBufferMatrix(): BufferMatrix = if (this is BufferMatrix) this else { - buildMatrix(rowNum, colNum) { i, j -> get(i, j) } - } - - public fun one(rows: Int, columns: Int): Matrix = VirtualMatrix(rows, columns) { i, j -> - if (i == j) 1.0 else 0.0 - } + DiagonalFeature - - override fun Matrix.unaryMinus(): Matrix = buildMatrix(rowNum, colNum) { i, j -> -get(i, j) } - - public override infix fun Matrix.dot(other: Matrix): BufferMatrix { - require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } - val bufferMatrix = toBufferMatrix() - val otherBufferMatrix = other.toBufferMatrix() - return buildMatrix(rowNum, other.colNum) { i, j -> - var res = 0.0 - for (l in 0 until colNum) { - res += bufferMatrix[i, l] * otherBufferMatrix[l, j] - } - res - } - } - - public override infix fun Matrix.dot(vector: Point): Point { - require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } - val bufferMatrix = toBufferMatrix() - return RealBuffer(rowNum) { i -> - var res = 0.0 - for (j in 0 until colNum) { - res += bufferMatrix[i, j] * vector[j] - } - res - } - } - - override fun add(a: Matrix, b: Matrix): BufferMatrix { - require(a.rowNum == b.rowNum) { "Row number mismatch in matrix addition. Left side: ${a.rowNum}, right side: ${b.rowNum}" } - require(a.colNum == b.colNum) { "Column number mismatch in matrix addition. Left side: ${a.colNum}, right side: ${b.colNum}" } - val aBufferMatrix = a.toBufferMatrix() - val bBufferMatrix = b.toBufferMatrix() - return buildMatrix(a.rowNum, a.colNum) { i, j -> - aBufferMatrix[i, j] + bBufferMatrix[i, j] - } - } - - override fun scale(a: Matrix, value: Double): BufferMatrix { - val bufferMatrix = a.toBufferMatrix() - return buildMatrix(a.rowNum, a.colNum) { i, j -> bufferMatrix[i, j] * value } - } - - override fun Matrix.times(value: Double): BufferMatrix = scale(this, value) +//public object RealLinearSpace: +//public object RealLinearSpace : LinearSpace, ScaleOperations> { // -// override fun multiply(a: Matrix, k: Number): BufferMatrix { -// val aBufferMatrix = a.toBufferMatrix() -// return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() } +// override val elementAlgebra: RealField get() = RealField +// +// public override fun buildMatrix( +// rows: Int, +// columns: Int, +// initializer: (i: Int, j: Int) -> Double, +// ): Matrix { +// val buffer = RealBuffer(rows * columns) { offset -> initializer(offset / columns, offset % columns) } +// return BufferMatrix(rows, columns, buffer) // } // -// override fun divide(a: Matrix, k: Number): BufferMatrix { -// val aBufferMatrix = a.toBufferMatrix() -// return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] / k.toDouble() } +// public fun Matrix.toBufferMatrix(): BufferMatrix = if (this is BufferMatrix) this else { +// buildMatrix(rowNum, colNum) { i, j -> get(i, j) } // } -} +// +// public fun one(rows: Int, columns: Int): Matrix = VirtualMatrix(rows, columns) { i, j -> +// if (i == j) 1.0 else 0.0 +// } + DiagonalFeature +// +// override fun Matrix.unaryMinus(): Matrix = buildMatrix(rowNum, colNum) { i, j -> -get(i, j) } +// +// public override infix fun Matrix.dot(other: Matrix): BufferMatrix { +// require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } +// val bufferMatrix = toBufferMatrix() +// val otherBufferMatrix = other.toBufferMatrix() +// return buildMatrix(rowNum, other.colNum) { i, j -> +// var res = 0.0 +// for (l in 0 until colNum) { +// res += bufferMatrix[i, l] * otherBufferMatrix[l, j] +// } +// res +// } +// } +// +// public override infix fun Matrix.dot(vector: Point): Point { +// require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } +// val bufferMatrix = toBufferMatrix() +// return RealBuffer(rowNum) { i -> +// var res = 0.0 +// for (j in 0 until colNum) { +// res += bufferMatrix[i, j] * vector[j] +// } +// res +// } +// } +// +// override fun add(a: Matrix, b: Matrix): BufferMatrix { +// require(a.rowNum == b.rowNum) { "Row number mismatch in matrix addition. Left side: ${a.rowNum}, right side: ${b.rowNum}" } +// require(a.colNum == b.colNum) { "Column number mismatch in matrix addition. Left side: ${a.colNum}, right side: ${b.colNum}" } +// val aBufferMatrix = a.toBufferMatrix() +// val bBufferMatrix = b.toBufferMatrix() +// return buildMatrix(a.rowNum, a.colNum) { i, j -> +// aBufferMatrix[i, j] + bBufferMatrix[i, j] +// } +// } +// +// override fun scale(a: Matrix, value: Double): BufferMatrix { +// val bufferMatrix = a.toBufferMatrix() +// return buildMatrix(a.rowNum, a.colNum) { i, j -> bufferMatrix[i, j] * value } +// } +// +// override fun Matrix.times(value: Double): BufferMatrix = scale(this, value) +// +//// +//// override fun multiply(a: Matrix, k: Number): BufferMatrix { +//// val aBufferMatrix = a.toBufferMatrix() +//// return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() } +//// } +//// +//// override fun divide(a: Matrix, k: Number): BufferMatrix { +//// val aBufferMatrix = a.toBufferMatrix() +//// return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] / k.toDouble() } +//// } +//} -/** - * Partially optimized real-valued matrix - */ -public val LinearSpace.Companion.real: RealLinearSpace get() = RealLinearSpace +///** +// * Partially optimized real-valued matrix +// */ +//public val LinearSpace.Companion.real: RealLinearSpace get() = RealLinearSpace diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt index 62e126694..48041df58 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt @@ -52,7 +52,7 @@ public interface NDStructure { * optimize operations and performance. If the feature is not present, null is defined. */ @UnstableKMathAPI - public fun getFeature(type: KClass): T? = null + public fun getFeature(type: KClass): F? = null public companion object { /** diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index c3f93ca55..339e06459 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -4,6 +4,7 @@ import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.getFeature +import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.ScaleOperations /** @@ -11,7 +12,9 @@ import space.kscience.kmath.operations.ScaleOperations * * @author Iaroslav Postovalov */ -public object EjmlLinearSpace : LinearSpace, ScaleOperations> { +public object EjmlLinearSpace : LinearSpace, ScaleOperations> { + + override val elementAlgebra: RealField get() = RealField /** * Converts this matrix to EJML one. @@ -25,43 +28,74 @@ public object EjmlLinearSpace : LinearSpace, ScaleOperations /** * Converts this vector to EJML one. */ - public fun Point.toEjml(): EjmlVector = - if (this is EjmlVector) this else EjmlVector(SimpleMatrix(size, 1).also { + public fun Vector.toEjml(): EjmlVector = when (this) { + is EjmlVector -> this + else -> EjmlVector(SimpleMatrix(size, 1).also { (0 until it.numRows()).forEach { row -> it[row, 0] = get(row) } }) + } - override fun buildMatrix(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): EjmlMatrix = + override fun buildMatrix(rows: Int, columns: Int, initializer: RealField.(i: Int, j: Int) -> Double): EjmlMatrix = EjmlMatrix(SimpleMatrix(rows, columns).also { (0 until rows).forEach { row -> - (0 until columns).forEach { col -> it[row, col] = initializer(row, col) } + (0 until columns).forEach { col -> it[row, col] = RealField.initializer(row, col) } } }) - override fun buildVector(size: Int, initializer: (Int) -> Double): Point = + override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Vector = EjmlVector(SimpleMatrix(size, 1).also { (0 until it.numRows()).forEach { row -> it[row, 0] = initializer(row) } }) + private fun SimpleMatrix.wrapMatrix() = EjmlMatrix(this) + private fun SimpleMatrix.wrapVector() = EjmlVector(this) - override fun Matrix.unaryMinus(): Matrix = this*(-1) + override fun Matrix.unaryMinus(): Matrix = this * (-1) public override fun Matrix.dot(other: Matrix): EjmlMatrix = EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) - public override fun Matrix.dot(vector: Point): EjmlVector = + public override fun Matrix.dot(vector: Vector): EjmlVector = EjmlVector(toEjml().origin.mult(vector.toEjml().origin)) - public override fun add(a: Matrix, b: Matrix): EjmlMatrix = - EjmlMatrix(a.toEjml().origin + b.toEjml().origin) - - public override operator fun Matrix.minus(b: Matrix): EjmlMatrix = - EjmlMatrix(toEjml().origin - b.toEjml().origin) + public override operator fun Matrix.minus(other: Matrix): EjmlMatrix = + EjmlMatrix(toEjml().origin - other.toEjml().origin) public override fun scale(a: Matrix, value: Double): EjmlMatrix = - buildMatrix(a.rowNum, a.colNum) { i, j -> a[i, j] * value } + a.toEjml().origin.scale(value).wrapMatrix() public override operator fun Matrix.times(value: Double): EjmlMatrix = EjmlMatrix(toEjml().origin.scale(value)) + + override fun Vector.unaryMinus(): EjmlVector = + toEjml().origin.negative().wrapVector() + + override fun Matrix.plus(other: Matrix): Matrix { + TODO("Not yet implemented") + } + + override fun Vector.plus(other: Vector): Vector { + TODO("Not yet implemented") + } + + override fun Vector.minus(other: Vector): Vector { + TODO("Not yet implemented") + } + + override fun Double.times(m: Matrix): Matrix { + TODO("Not yet implemented") + } + + override fun Vector.times(value: Double): Vector { + TODO("Not yet implemented") + } + + override fun Double.times(v: Vector): Vector { + TODO("Not yet implemented") + } + + public override fun add(a: Matrix, b: Matrix): EjmlMatrix = + EjmlMatrix(a.toEjml().origin + b.toEjml().origin) } /** diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index d23e613e4..a1984fa31 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -85,7 +85,7 @@ public class EjmlMatrix(public val origin: SimpleMatrix) : Matrix { override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is Matrix<*>) return false + if (other !is NDStructure<*>) return false return NDStructure.contentEquals(this, other) } From d5ba816b7daa64a089c3b07e4aa28ab1e10b74f8 Mon Sep 17 00:00:00 2001 From: darksnake Date: Sat, 13 Mar 2021 18:00:47 +0300 Subject: [PATCH 063/393] WIP Matrix refactor --- .../kscience/kmath/linear/LinearSpace.kt | 2 +- .../kscience/kmath/linear/LupDecomposition.kt | 4 +- .../space/kscience/kmath/linear/MatrixTest.kt | 3 +- .../kscience/kmath/dimensions/Wrappers.kt | 31 +++++++------ .../kscience/kmath/ejml/EjmlLinearSpace.kt | 39 ++++++---------- .../space/kscience/kmath/real/RealMatrix.kt | 29 ++++++------ .../kotlin/space/kscience/kmath/real/dot.kt | 46 +++++++++---------- 7 files changed, 74 insertions(+), 80 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 5800bdd0d..4a9d2c9b3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -22,7 +22,7 @@ public typealias Vector = Point * @param T the type of items in the matrices. * @param M the type of operated matrices. */ -public interface LinearSpace> { +public interface LinearSpace> { public val elementAlgebra: A /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt index 5d68534bc..0937f1e19 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt @@ -228,7 +228,7 @@ public inline fun > LinearSpace>.inverseWi @OptIn(UnstableKMathAPI::class) -public fun RealLinearSpace.solveWithLup(a: Matrix, b: Matrix): Matrix { +public fun LinearSpace.solveWithLup(a: Matrix, b: Matrix): Matrix { // Use existing decomposition if it is provided by matrix val bufferFactory: MutableBufferFactory = MutableBuffer.Companion::real val decomposition: LupDecomposition = a.getFeature() ?: lup(bufferFactory, a) { it < 1e-11 } @@ -238,5 +238,5 @@ public fun RealLinearSpace.solveWithLup(a: Matrix, b: Matrix): M /** * Inverses a square matrix using LUP decomposition. Non square matrix will throw a error. */ -public fun RealLinearSpace.inverseWithLup(matrix: Matrix): Matrix = +public fun LinearSpace.inverseWithLup(matrix: Matrix): Matrix = solveWithLup(matrix, one(matrix.rowNum, matrix.colNum)) \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt index 5cf83889a..27374e93f 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt @@ -2,7 +2,6 @@ package space.kscience.kmath.linear import space.kscience.kmath.nd.NDStructure import space.kscience.kmath.nd.as2D -import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals @@ -17,7 +16,7 @@ class MatrixTest { @Test fun testBuilder() { - val matrix = Matrix.build(2, 3)( + val matrix = LinearSpace.real.matrix(2, 3)( 1.0, 0.0, 0.0, 0.0, 1.0, 2.0 ) diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt index 89ff97f14..f7e14b29f 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt @@ -2,7 +2,8 @@ package space.kscience.kmath.dimensions import space.kscience.kmath.linear.* import space.kscience.kmath.nd.Structure2D -import space.kscience.kmath.operations.invoke +import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.Ring /** * A matrix with compile-time controlled dimension @@ -77,7 +78,7 @@ public inline class DPointWrapper(public val point: Point) /** * Basic operations on dimension-safe matrices. Operates on [Matrix] */ -public inline class DMatrixContext(public val context: LinearSpace>) { +public inline class DMatrixContext>(public val context: LinearSpace) { public inline fun Matrix.coerce(): DMatrix { require(rowNum == Dimension.dim().toInt()) { "Row number mismatch: expected ${Dimension.dim()} but found $rowNum" @@ -93,13 +94,15 @@ public inline class DMatrixContext(public val context: LinearSpace produce(noinline initializer: (i: Int, j: Int) -> T): DMatrix { + public inline fun produce( + noinline initializer: A.(i: Int, j: Int) -> T + ): DMatrix { val rows = Dimension.dim() val cols = Dimension.dim() return context.buildMatrix(rows.toInt(), cols.toInt(), initializer).coerce() } - public inline fun point(noinline initializer: (Int) -> T): DPoint { + public inline fun point(noinline initializer: A.(Int) -> T): DPoint { val size = Dimension.dim() return DPoint.coerceUnsafe( @@ -112,31 +115,31 @@ public inline class DMatrixContext(public val context: LinearSpace DMatrix.dot( other: DMatrix, - ): DMatrix = context { this@dot dot other }.coerce() + ): DMatrix = context.run { this@dot dot other }.coerce() public inline infix fun DMatrix.dot(vector: DPoint): DPoint = - DPoint.coerceUnsafe(context { this@dot dot vector }) + DPoint.coerceUnsafe(context.run { this@dot dot vector }) public inline operator fun DMatrix.times(value: T): DMatrix = - context { this@times.times(value) }.coerce() + context.run { this@times.times(value) }.coerce() public inline operator fun T.times(m: DMatrix): DMatrix = m * this public inline operator fun DMatrix.plus(other: DMatrix): DMatrix = - context { this@plus + other }.coerce() + context.run { this@plus + other }.coerce() public inline operator fun DMatrix.minus(other: DMatrix): DMatrix = - context { this@minus + other }.coerce() + context.run { this@minus + other }.coerce() public inline operator fun DMatrix.unaryMinus(): DMatrix = - context { this@unaryMinus.unaryMinus() }.coerce() + context.run { this@unaryMinus.unaryMinus() }.coerce() public inline fun DMatrix.transpose(): DMatrix = - context { (this@transpose as Matrix).transpose() }.coerce() + context.run { (this@transpose as Matrix).transpose() }.coerce() public companion object { - public val real: DMatrixContext = DMatrixContext(LinearSpace.real) + public val real: DMatrixContext = DMatrixContext(LinearSpace.real) } } @@ -144,11 +147,11 @@ public inline class DMatrixContext(public val context: LinearSpace DMatrixContext.one(): DMatrix = produce { i, j -> +public inline fun DMatrixContext.one(): DMatrix = produce { i, j -> if (i == j) 1.0 else 0.0 } -public inline fun DMatrixContext.zero(): DMatrix = +public inline fun DMatrixContext.zero(): DMatrix = produce { _, _ -> 0.0 } \ No newline at end of file diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index 339e06459..57ce977fd 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -44,7 +44,7 @@ public object EjmlLinearSpace : LinearSpace, ScaleOperations< override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Vector = EjmlVector(SimpleMatrix(size, 1).also { - (0 until it.numRows()).forEach { row -> it[row, 0] = initializer(row) } + (0 until it.numRows()).forEach { row -> it[row, 0] = RealField.initializer(row) } }) private fun SimpleMatrix.wrapMatrix() = EjmlMatrix(this) @@ -59,43 +59,34 @@ public object EjmlLinearSpace : LinearSpace, ScaleOperations< EjmlVector(toEjml().origin.mult(vector.toEjml().origin)) public override operator fun Matrix.minus(other: Matrix): EjmlMatrix = - EjmlMatrix(toEjml().origin - other.toEjml().origin) + (toEjml().origin - other.toEjml().origin).wrapMatrix() public override fun scale(a: Matrix, value: Double): EjmlMatrix = a.toEjml().origin.scale(value).wrapMatrix() public override operator fun Matrix.times(value: Double): EjmlMatrix = - EjmlMatrix(toEjml().origin.scale(value)) + toEjml().origin.scale(value).wrapMatrix() override fun Vector.unaryMinus(): EjmlVector = toEjml().origin.negative().wrapVector() - override fun Matrix.plus(other: Matrix): Matrix { - TODO("Not yet implemented") - } + override fun Matrix.plus(other: Matrix): EjmlMatrix = + (toEjml().origin + other.toEjml().origin).wrapMatrix() - override fun Vector.plus(other: Vector): Vector { - TODO("Not yet implemented") - } + override fun Vector.plus(other: Vector): EjmlVector = + (toEjml().origin + other.toEjml().origin).wrapVector() - override fun Vector.minus(other: Vector): Vector { - TODO("Not yet implemented") - } + override fun Vector.minus(other: Vector): EjmlVector = + (toEjml().origin - other.toEjml().origin).wrapVector() - override fun Double.times(m: Matrix): Matrix { - TODO("Not yet implemented") - } + override fun Double.times(m: Matrix): EjmlMatrix = + m.toEjml().origin.scale(this).wrapMatrix() - override fun Vector.times(value: Double): Vector { - TODO("Not yet implemented") - } + override fun Vector.times(value: Double): EjmlVector = + toEjml().origin.scale(value).wrapVector() - override fun Double.times(v: Vector): Vector { - TODO("Not yet implemented") - } - - public override fun add(a: Matrix, b: Matrix): EjmlMatrix = - EjmlMatrix(a.toEjml().origin + b.toEjml().origin) + override fun Double.times(v: Vector): EjmlVector = + v.toEjml().origin.scale(this).wrapVector() } /** diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt index b93c430f9..640615cc9 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt @@ -2,6 +2,7 @@ package space.kscience.kmath.real import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.RealField import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.asIterable @@ -21,11 +22,11 @@ import kotlin.math.pow public typealias RealMatrix = Matrix -public fun realMatrix(rowNum: Int, colNum: Int, initializer: (i: Int, j: Int) -> Double): RealMatrix = +public fun realMatrix(rowNum: Int, colNum: Int, initializer: RealField.(i: Int, j: Int) -> Double): RealMatrix = LinearSpace.real.buildMatrix(rowNum, colNum, initializer) public fun Array.toMatrix(): RealMatrix { - return LinearSpace.real.buildMatrix(size, this[0].size) { row, col -> this[row][col] } + return LinearSpace.real.buildMatrix(size, this[0].size) { row, col -> this@toMatrix[row][col] } } public fun Sequence.toMatrix(): RealMatrix = toList().let { @@ -43,37 +44,37 @@ public fun RealMatrix.repeatStackVertical(n: Int): RealMatrix = public operator fun RealMatrix.times(double: Double): RealMatrix = LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> - this[row, col] * double + get(row, col) * double } public operator fun RealMatrix.plus(double: Double): RealMatrix = LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> - this[row, col] + double + get(row, col) + double } public operator fun RealMatrix.minus(double: Double): RealMatrix = LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> - this[row, col] - double + get(row, col) - double } public operator fun RealMatrix.div(double: Double): RealMatrix = LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> - this[row, col] / double + get(row, col) / double } public operator fun Double.times(matrix: RealMatrix): RealMatrix = LinearSpace.real.buildMatrix(matrix.rowNum, matrix.colNum) { row, col -> - this * matrix[row, col] + this@times * matrix[row, col] } public operator fun Double.plus(matrix: RealMatrix): RealMatrix = LinearSpace.real.buildMatrix(matrix.rowNum, matrix.colNum) { row, col -> - this + matrix[row, col] + this@plus + matrix[row, col] } public operator fun Double.minus(matrix: RealMatrix): RealMatrix = LinearSpace.real.buildMatrix(matrix.rowNum, matrix.colNum) { row, col -> - this - matrix[row, col] + this@minus - matrix[row, col] } // TODO: does this operation make sense? Should it be 'this/matrix[row, col]'? @@ -87,13 +88,13 @@ public operator fun Double.minus(matrix: RealMatrix): RealMatrix = @UnstableKMathAPI public operator fun RealMatrix.times(other: RealMatrix): RealMatrix = - LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> this[row, col] * other[row, col] } + LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> this@times[row, col] * other[row, col] } public operator fun RealMatrix.plus(other: RealMatrix): RealMatrix = - LinearSpace.real.add(this, other) + LinearSpace.real.run { this@plus + other } public operator fun RealMatrix.minus(other: RealMatrix): RealMatrix = - LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> this[row, col] - other[row, col] } + LinearSpace.real.buildMatrix(rowNum, colNum) { row, col -> this@minus[row, col] - other[row, col] } /* * Operations on columns @@ -102,14 +103,14 @@ public operator fun RealMatrix.minus(other: RealMatrix): RealMatrix = public inline fun RealMatrix.appendColumn(crossinline mapper: (Buffer) -> Double): RealMatrix = LinearSpace.real.buildMatrix(rowNum, colNum + 1) { row, col -> if (col < colNum) - this[row, col] + get(row, col) else mapper(rows[row]) } public fun RealMatrix.extractColumns(columnRange: IntRange): RealMatrix = LinearSpace.real.buildMatrix(rowNum, columnRange.count()) { row, col -> - this[row, columnRange.first + col] + this@extractColumns[row, columnRange.first + col] } public fun RealMatrix.extractColumn(columnIndex: Int): RealMatrix = diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt index cbfb364c1..5a66b55bd 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt @@ -1,31 +1,31 @@ package space.kscience.kmath.real -import space.kscience.kmath.linear.BufferMatrix -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.linear.LinearSpace +import space.kscience.kmath.nd.Matrix /** * Optimized dot product for real matrices */ -public infix fun BufferMatrix.dot(other: BufferMatrix): BufferMatrix { - require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } - val resultArray = DoubleArray(this.rowNum * other.colNum) - - //convert to array to insure there is no memory indirection - fun Buffer.unsafeArray() = if (this is RealBuffer) - this.array - else - DoubleArray(size) { get(it) } - - val a = this.buffer.unsafeArray() - val b = other.buffer.unsafeArray() - - for (i in (0 until rowNum)) - for (j in (0 until other.colNum)) - for (k in (0 until colNum)) - resultArray[i * other.colNum + j] += a[i * colNum + k] * b[k * other.colNum + j] - - val buffer = RealBuffer(resultArray) - return BufferMatrix(rowNum, other.colNum, buffer) +public infix fun Matrix.dot(other: Matrix): Matrix = LinearSpace.real.run{ + this@dot dot other +// require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } +// val resultArray = DoubleArray(this.rowNum * other.colNum) +// +// //convert to array to insure there is no memory indirection +// fun Buffer.unsafeArray() = if (this is RealBuffer) +// this.array +// else +// DoubleArray(size) { get(it) } +// +// val a = this.buffer.unsafeArray() +// val b = other.buffer.unsafeArray() +// +// for (i in (0 until rowNum)) +// for (j in (0 until other.colNum)) +// for (k in (0 until colNum)) +// resultArray[i * other.colNum + j] += a[i * colNum + k] * b[k * other.colNum + j] +// +// val buffer = RealBuffer(resultArray) +// return BufferMatrix(rowNum, other.colNum, buffer) } \ No newline at end of file From 5e6f65a181c1a04cf5b992ab350972cb41d6ac93 Mon Sep 17 00:00:00 2001 From: darksnake Date: Sat, 13 Mar 2021 18:19:10 +0300 Subject: [PATCH 064/393] WIP Matrix refactor --- .../kmath/structures/typeSafeDimensions.kt | 4 +- .../kscience/kmath/commons/linear/CMMatrix.kt | 4 +- .../kscience/kmath/commons/linear/CMSolver.kt | 4 +- .../kscience/kmath/linear/MatrixBuilder.kt | 25 ++++++++++-- .../space/kscience/kmath/linear/MatrixTest.kt | 2 +- .../kscience/kmath/linear/RealLUSolverTest.kt | 14 +++---- .../kmath/structures/NumberNDFieldTest.kt | 5 ++- .../kotlin/space/kscience/kmath/real/dot.kt | 19 ---------- .../kaceince/kmath/real/RealMatrixTest.kt | 38 +++++++++---------- .../kaceince/kmath/real/RealVectorTest.kt | 4 +- 10 files changed, 60 insertions(+), 59 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt index fdd631238..d2d130ab4 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt @@ -5,7 +5,7 @@ import space.kscience.kmath.dimensions.D3 import space.kscience.kmath.dimensions.DMatrixContext import space.kscience.kmath.dimensions.Dimension -private fun DMatrixContext.simple() { +private fun DMatrixContext.simple() { val m1 = produce { i, j -> (i + j).toDouble() } val m2 = produce { i, j -> (i + j).toDouble() } @@ -17,7 +17,7 @@ private object D5 : Dimension { override val dim: UInt = 5u } -private fun DMatrixContext.custom() { +private fun DMatrixContext.custom() { val m1 = produce { i, j -> (i + j).toDouble() } val m2 = produce { i, j -> (i - j).toDouble() } val m3 = produce { i, j -> (i - j).toDouble() } diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index c1c3d716a..b462a1a36 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -99,8 +99,8 @@ public object CMLinearSpace : LinearSpace { ArrayRealVector(array).wrap() } - private fun RealMatrix.wrap(): CMMatrix = CMMatrix(this) - private fun RealVector.wrap(): CMVector = CMVector(this) + internal fun RealMatrix.wrap(): CMMatrix = CMMatrix(this) + internal fun RealVector.wrap(): CMVector = CMVector(this) override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Vector = ArrayRealVector(DoubleArray(size) { RealField.initializer(it) }).wrap() diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt index ff4727aa2..b5fd0154e 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt @@ -27,7 +27,7 @@ public fun CMLinearSpace.solve( a: Matrix, b: Matrix, decomposition: CMDecomposition = CMDecomposition.LUP -): CMMatrix = solver(a, decomposition).solve(b.toCM().origin).asMatrix() +): CMMatrix = solver(a, decomposition).solve(b.toCM().origin).wrap() public fun CMLinearSpace.solve( a: Matrix, @@ -38,4 +38,4 @@ public fun CMLinearSpace.solve( public fun CMLinearSpace.inverse( a: Matrix, decomposition: CMDecomposition = CMDecomposition.LUP -): CMMatrix = solver(a, decomposition).inverse.asMatrix() +): CMMatrix = solver(a, decomposition).inverse.wrap() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt index 28df78dad..6814cb561 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt @@ -3,11 +3,30 @@ package space.kscience.kmath.linear import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring +public class MatrixBuilder>( + public val linearSpace: LinearSpace, + public val rows: Int, + public val columns: Int, +) { + public operator fun invoke(vararg elements: T): Matrix { + require(rows * columns == elements.size) { "The number of elements ${elements.size} is not equal $rows * $columns" } + return linearSpace.buildMatrix(rows, columns) { i, j -> elements[i * columns + j] } + } + + //TODO add specific matrix builder functions like diagonal, etc +} @UnstableKMathAPI -public fun LinearSpace>.matrix(rows: Int, columns: Int, vararg elements: T): Matrix { - require(rows * columns == elements.size) { "The number of elements ${elements.size} is not equal $rows * $columns" } - return buildMatrix(rows, columns) { i, j -> elements[i * columns + j] } +public fun > LinearSpace.matrix(rows: Int, columns: Int): MatrixBuilder = + MatrixBuilder(this, rows, columns) + +/** + * Build a square matrix from given elements. + */ +@UnstableKMathAPI +public fun LinearSpace>.square(vararg elements: T): Matrix { + val size: Int = kotlin.math.sqrt(elements.size.toDouble()).toInt() + return matrix(size,size)(*elements) } @UnstableKMathAPI diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt index 27374e93f..53cdd4522 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt @@ -38,7 +38,7 @@ class MatrixTest { infix fun Matrix.pow(power: Int): Matrix { var res = this repeat(power - 1) { - res = RealLinearSpace.invoke { res dot this@pow } + res = LinearSpace.real.run { res dot this@pow } } return res } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt index 4d6b8f5be..802849a1e 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt @@ -14,12 +14,12 @@ class RealLUSolverTest { @Test fun testDecomposition() { - val matrix = Matrix.square( - 3.0, 1.0, - 1.0, 3.0 - ) - LinearSpace.real.run { + val matrix = square( + 3.0, 1.0, + 1.0, 3.0 + ) + val lup = lup(matrix) //Check determinant @@ -31,14 +31,14 @@ class RealLUSolverTest { @Test fun testInvert() { - val matrix = Matrix.square( + val matrix = LinearSpace.real.square( 3.0, 1.0, 1.0, 3.0 ) val inverted = LinearSpace.real.inverseWithLup(matrix) - val expected = Matrix.square( + val expected = LinearSpace.real.square( 0.375, -0.125, -0.125, 0.375 ) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt index 23b0e7348..dd7871f9a 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.structures +import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.nd.* import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.invoke @@ -33,7 +34,9 @@ class NumberNDFieldTest { @Test fun testGeneration() { - val array = Structure2D.real(3, 3) { i, j -> (i * 10 + j).toDouble() } + val array = LinearSpace.real.buildMatrix(3, 3) { i, j -> + (i * 10 + j).toDouble() + } for (i in 0..2) { for (j in 0..2) { diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt index 5a66b55bd..1a7c1213c 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt @@ -9,23 +9,4 @@ import space.kscience.kmath.nd.Matrix */ public infix fun Matrix.dot(other: Matrix): Matrix = LinearSpace.real.run{ this@dot dot other -// require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } -// val resultArray = DoubleArray(this.rowNum * other.colNum) -// -// //convert to array to insure there is no memory indirection -// fun Buffer.unsafeArray() = if (this is RealBuffer) -// this.array -// else -// DoubleArray(size) { get(it) } -// -// val a = this.buffer.unsafeArray() -// val b = other.buffer.unsafeArray() -// -// for (i in (0 until rowNum)) -// for (j in (0 until other.colNum)) -// for (k in (0 until colNum)) -// resultArray[i * other.colNum + j] += a[i * colNum + k] * b[k * other.colNum + j] -// -// val buffer = RealBuffer(resultArray) -// return BufferMatrix(rowNum, other.colNum, buffer) } \ No newline at end of file diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt index 9e2778be9..6ab11b03b 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt @@ -1,7 +1,7 @@ package kaceince.kmath.real -import space.kscience.kmath.linear.Matrix -import space.kscience.kmath.linear.build +import space.kscience.kmath.linear.LinearSpace +import space.kscience.kmath.linear.matrix import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.real.* import space.kscience.kmath.structures.contentEquals @@ -30,11 +30,11 @@ internal class RealMatrixTest { @Test fun testRepeatStackVertical() { - val matrix1 = Matrix.build(2, 3)( + val matrix1 = LinearSpace.real.matrix(2, 3)( 1.0, 0.0, 0.0, 0.0, 1.0, 2.0 ) - val matrix2 = Matrix.build(6, 3)( + val matrix2 = LinearSpace.real.matrix(6, 3)( 1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 1.0, 0.0, 0.0, @@ -47,12 +47,12 @@ internal class RealMatrixTest { @Test fun testMatrixAndDouble() { - val matrix1 = Matrix.build(2, 3)( + val matrix1 = LinearSpace.real.matrix(2, 3)( 1.0, 0.0, 3.0, 4.0, 6.0, 2.0 ) val matrix2 = (matrix1 * 2.5 + 1.0 - 2.0) / 2.0 - val expectedResult = Matrix.build(2, 3)( + val expectedResult = LinearSpace.real.matrix(2, 3)( 0.75, -0.5, 3.25, 4.5, 7.0, 2.0 ) @@ -61,13 +61,13 @@ internal class RealMatrixTest { @Test fun testDoubleAndMatrix() { - val matrix1 = Matrix.build(2, 3)( + val matrix1 = LinearSpace.real.matrix(2, 3)( 1.0, 0.0, 3.0, 4.0, 6.0, 2.0 ) val matrix2 = 20.0 - (10.0 + (5.0 * matrix1)) //val matrix2 = 10.0 + (5.0 * matrix1) - val expectedResult = Matrix.build(2, 3)( + val expectedResult = LinearSpace.real.matrix(2, 3)( 5.0, 10.0, -5.0, -10.0, -20.0, 0.0 ) @@ -76,15 +76,15 @@ internal class RealMatrixTest { @Test fun testSquareAndPower() { - val matrix1 = Matrix.build(2, 3)( + val matrix1 = LinearSpace.real.matrix(2, 3)( -1.0, 0.0, 3.0, 4.0, -6.0, -2.0 ) - val matrix2 = Matrix.build(2, 3)( + val matrix2 = LinearSpace.real.matrix(2, 3)( 1.0, 0.0, 9.0, 16.0, 36.0, 4.0 ) - val matrix3 = Matrix.build(2, 3)( + val matrix3 = LinearSpace.real.matrix(2, 3)( -1.0, 0.0, 27.0, 64.0, -216.0, -8.0 ) @@ -95,16 +95,16 @@ internal class RealMatrixTest { @OptIn(UnstableKMathAPI::class) @Test fun testTwoMatrixOperations() { - val matrix1 = Matrix.build(2, 3)( + val matrix1 = LinearSpace.real.matrix(2, 3)( -1.0, 0.0, 3.0, 4.0, -6.0, 7.0 ) - val matrix2 = Matrix.build(2, 3)( + val matrix2 = LinearSpace.real.matrix(2, 3)( 1.0, 0.0, 3.0, 4.0, 6.0, -2.0 ) val result = matrix1 * matrix2 + matrix1 - matrix2 - val expectedResult = Matrix.build(2, 3)( + val expectedResult = LinearSpace.real.matrix(2, 3)( -3.0, 0.0, 9.0, 16.0, -48.0, -5.0 ) @@ -113,16 +113,16 @@ internal class RealMatrixTest { @Test fun testColumnOperations() { - val matrix1 = Matrix.build(2, 4)( + val matrix1 = LinearSpace.real.matrix(2, 4)( -1.0, 0.0, 3.0, 15.0, 4.0, -6.0, 7.0, -11.0 ) - val matrix2 = Matrix.build(2, 5)( + val matrix2 = LinearSpace.real.matrix(2, 5)( -1.0, 0.0, 3.0, 15.0, -1.0, 4.0, -6.0, 7.0, -11.0, 4.0 ) - val col1 = Matrix.build(2, 1)(0.0, -6.0) - val cols1to2 = Matrix.build(2, 2)( + val col1 = LinearSpace.real.matrix(2, 1)(0.0, -6.0) + val cols1to2 = LinearSpace.real.matrix(2, 2)( 0.0, 3.0, -6.0, 7.0 ) @@ -147,7 +147,7 @@ internal class RealMatrixTest { @Test fun testAllElementOperations() { - val matrix1 = Matrix.build(2, 4)( + val matrix1 = LinearSpace.real.matrix(2, 4)( -1.0, 0.0, 3.0, 15.0, 4.0, -6.0, 7.0, -11.0 ) diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt index 5d032de67..59d55110f 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt @@ -2,9 +2,7 @@ package kaceince.kmath.real import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.asMatrix -import space.kscience.kmath.linear.real import space.kscience.kmath.linear.transpose -import space.kscience.kmath.operations.invoke import space.kscience.kmath.real.plus import space.kscience.kmath.structures.Buffer import kotlin.test.Test @@ -32,7 +30,7 @@ internal class RealVectorTest { val vector2 = Buffer.real(5) { 5 - it.toDouble() } val matrix1 = vector1.asMatrix() val matrix2 = vector2.asMatrix().transpose() - val product = LinearSpace.real { matrix1 dot matrix2 } + val product = LinearSpace.real.run { matrix1 dot matrix2 } assertEquals(5.0, product[1, 0]) assertEquals(6.0, product[2, 2]) } From 0911efd4aa1944c89cb9df4913c251daef98d31c Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sat, 13 Mar 2021 19:30:58 +0300 Subject: [PATCH 065/393] add buffered tensor + lu --- .../kscience/kmath/tensors/BufferTensor.kt | 33 --------- .../kscience/kmath/tensors/BufferedTensor.kt | 33 +++++++++ .../kmath/tensors/RealTensorAlgebra.kt | 69 +++++++++++++++---- .../kscience/kmath/tensors/TensorAlgebra.kt | 5 +- 4 files changed, 92 insertions(+), 48 deletions(-) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt deleted file mode 100644 index 817c51f11..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferTensor.kt +++ /dev/null @@ -1,33 +0,0 @@ -package space.kscience.kmath.tensors - -import space.kscience.kmath.linear.BufferMatrix -import space.kscience.kmath.linear.RealMatrixContext.toBufferMatrix -import space.kscience.kmath.nd.Matrix -import space.kscience.kmath.nd.MutableNDBuffer -import space.kscience.kmath.nd.Structure2D -import space.kscience.kmath.nd.as2D -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferAccessor2D -import space.kscience.kmath.structures.MutableBuffer -import space.kscience.kmath.structures.toList - -public open class BufferTensor( - override val shape: IntArray, - buffer: MutableBuffer -) : - TensorStructure, - MutableNDBuffer( - TensorStrides(shape), - buffer - ) - - -public fun BufferTensor.toBufferMatrix(): BufferMatrix { - return BufferMatrix(shape[0], shape[1], this.buffer) -} - -// T??? -public fun BufferMatrix.BufferTensor(): BufferTensor { - return BufferTensor(intArrayOf(rowNum, colNum), BufferAccessor2D(rowNum, colNum, Buffer.Companion::real).create(this)) -} - diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt new file mode 100644 index 000000000..9ffe2db61 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -0,0 +1,33 @@ +package space.kscience.kmath.tensors + +import space.kscience.kmath.linear.BufferMatrix +import space.kscience.kmath.nd.MutableNDBuffer +import space.kscience.kmath.structures.* +import space.kscience.kmath.structures.BufferAccessor2D + +public open class BufferedTensor( + override val shape: IntArray, + buffer: MutableBuffer +) : + TensorStructure, + MutableNDBuffer( + TensorStrides(shape), + buffer + ) { + + public operator fun get(i: Int, j: Int): T{ + check(this.dimension == 2) {"Not matrix"} + return this[intArrayOf(i, j)] + } + + public operator fun set(i: Int, j: Int, value: T): Unit{ + check(this.dimension == 2) {"Not matrix"} + this[intArrayOf(i, j)] = value + } + +} + +public class IntTensor( + shape: IntArray, + buffer: IntArray +) : BufferedTensor(shape, IntBuffer(buffer)) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index e38056097..3e21a3a98 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,24 +1,19 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.linear.BufferMatrix -import space.kscience.kmath.linear.RealMatrixContext.toBufferMatrix -import space.kscience.kmath.nd.MutableNDBuffer -import space.kscience.kmath.nd.as2D -import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array -import space.kscience.kmath.structures.toList +import kotlin.math.abs public class RealTensor( shape: IntArray, buffer: DoubleArray -) : BufferTensor(shape, RealBuffer(buffer)) +) : BufferedTensor(shape, RealBuffer(buffer)) public class RealTensorAlgebra : TensorPartialDivisionAlgebra { override fun RealTensor.value(): Double { - check(this.shape contentEquals intArrayOf(1)) { + check(this.shape contentEquals intArrayOf(1)) { "Inconsistent value for tensor of shape ${shape.toList()}" } return this.buffer.array[0] @@ -51,7 +46,8 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { - TODO() + override fun RealTensor.lu(): Pair { + // todo checks + val lu = this.copy() + val m = this.shape[0] + val pivot = IntArray(m) + + + // Initialize permutation array and parity + for (row in 0 until m) pivot[row] = row + var even = true + + for (i in 0 until m) { + var maxA = -1.0 + var iMax = i + + for (k in i until m) { + val absA = abs(lu[k, i]) + if (absA > maxA) { + maxA = absA + iMax = k + } + } + + //todo check singularity + + if (iMax != i) { + + val j = pivot[i] + pivot[i] = pivot[iMax] + pivot[iMax] = j + even != even + + for (k in 0 until m) { + val tmp = lu[i, k] + lu[i, k] = lu[iMax, k] + lu[iMax, k] = tmp + } + + } + + for (j in i + 1 until m) { + lu[j, i] /= lu[i, i] + for (k in i + 1 until m) { + lu[j, k] -= lu[j, i] * lu[i, k] + } + } + } + return Pair(lu, IntTensor(intArrayOf(m), pivot)) } - override fun luUnpack(A_LU: RealTensor, pivots: RealTensor): Triple { - TODO("Not yet implemented") + override fun luUnpack(A_LU: RealTensor, pivots: IntTensor): Triple { + // todo checks + } override fun RealTensor.svd(): Triple { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 6f42623e0..0dbcae044 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -78,11 +78,12 @@ public interface TensorPartialDivisionAlgebra public fun TensorType.log(): TensorType public fun TensorType.logAssign(): Unit + // todo change type of pivots //https://pytorch.org/docs/stable/generated/torch.lu.html - public fun TensorType.lu(): Pair + public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun luUnpack(A_LU: TensorType, pivots: TensorType): Triple + public fun luUnpack(A_LU: TensorType, pivots: IntTensor): Triple //https://pytorch.org/docs/stable/generated/torch.svd.html public fun TensorType.svd(): Triple From 8f88a101d24faee0504228c57642bb980a7d48e4 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sat, 13 Mar 2021 20:51:15 +0300 Subject: [PATCH 066/393] complete lu for matrix --- .../kmath/tensors/RealTensorAlgebra.kt | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 9e040fcd8..f91f44519 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -35,7 +35,10 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { + override fun luUnpack(lu: RealTensor, pivots: IntTensor): Triple { // todo checks + val n = lu.shape[0] + val p = zeroesLike(lu) + pivots.buffer.array.forEachIndexed { i, pivot -> + p[i, pivot] = 1.0 + } + val l = zeroesLike(lu) + val u = zeroesLike(lu) + for (i in 0 until n){ + for (j in 0 until n){ + if (i == j) { + l[i, j] = 1.0 + } + if (j < i) { + l[i, j] = lu[i, j] + } + if (j >= i) { + u[i, j] = lu[i, j] + } + } + } + return Triple(p, l, u) } override fun RealTensor.svd(): Triple { From be9398b3226bebf2a5afbd561c6b5fb816fbde9e Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 13 Mar 2021 21:22:18 +0300 Subject: [PATCH 067/393] Vector space refactor --- kmath-core/api/kmath-core.api | 327 ++++-------------- .../kscience/kmath/linear/MatrixBuilder.kt | 12 +- .../kscience/kmath/linear/VirtualMatrix.kt | 10 +- .../space/kscience/kmath/nd/Structure2D.kt | 11 +- .../space/kscience/kmath/linear/MatrixTest.kt | 2 + .../kscience/kmath/linear/RealLUSolverTest.kt | 8 +- .../space/kscience/kmath/real/RealMatrix.kt | 4 + .../kaceince/kmath/real/RealMatrixTest.kt | 31 +- 8 files changed, 105 insertions(+), 300 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 8b30e4c05..c1f8d5ec5 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -432,108 +432,6 @@ public final class space/kscience/kmath/expressions/SymbolIndexerKt { public static final fun withSymbols ([Lspace/kscience/kmath/expressions/Symbol;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } -public final class space/kscience/kmath/linear/BufferMatrix : space/kscience/kmath/nd/Structure2D { - public fun (IILspace/kscience/kmath/structures/Buffer;)V - public fun elements ()Lkotlin/sequences/Sequence; - public fun equals (Ljava/lang/Object;)Z - public fun get (II)Ljava/lang/Object; - public fun get ([I)Ljava/lang/Object; - public final fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; - public fun getColNum ()I - public fun getColumns ()Lspace/kscience/kmath/structures/Buffer; - public fun getDimension ()I - public fun getRowNum ()I - public fun getRows ()Lspace/kscience/kmath/structures/Buffer; - public fun getShape ()[I - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class space/kscience/kmath/linear/BufferMatrixContext : space/kscience/kmath/linear/GenericMatrixContext { - public static final field Companion Lspace/kscience/kmath/linear/BufferMatrixContext$Companion; - public fun (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V - public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun add (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun add (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; - public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun getElementContext ()Lspace/kscience/kmath/operations/Ring; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public final fun one (II)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun point (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; - public fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; - public fun scale (Lspace/kscience/kmath/nd/Structure2D;D)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; - public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; -} - -public final class space/kscience/kmath/linear/BufferMatrixContext$Companion { -} - -public final class space/kscience/kmath/linear/BufferVectorSpace : space/kscience/kmath/linear/VectorSpace { - public fun (ILspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;)V - public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun add (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public fun getAlgebra ()Lspace/kscience/kmath/operations/Group; - public final fun getBufferFactory ()Lkotlin/jvm/functions/Function2; - public fun getSize ()I - public synthetic fun getZero ()Ljava/lang/Object; - public fun getZero ()Lspace/kscience/kmath/structures/Buffer; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; - public fun scale (Lspace/kscience/kmath/structures/Buffer;D)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; -} - public abstract interface class space/kscience/kmath/linear/CholeskyDecompositionFeature : space/kscience/kmath/linear/MatrixFeature { public abstract fun getL ()Lspace/kscience/kmath/nd/Structure2D; } @@ -549,37 +447,6 @@ public abstract interface class space/kscience/kmath/linear/DiagonalFeature : sp public final class space/kscience/kmath/linear/DiagonalFeature$Companion : space/kscience/kmath/linear/DiagonalFeature { } -public abstract interface class space/kscience/kmath/linear/GenericMatrixContext : space/kscience/kmath/linear/MatrixContext { - public abstract fun add (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun getElementContext ()Lspace/kscience/kmath/operations/Ring; - public abstract fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; -} - -public final class space/kscience/kmath/linear/GenericMatrixContext$DefaultImpls { - public static fun add (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun binaryOperation (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun binaryOperationFunction (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D; - public static fun div (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; - public static fun dot (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun dot (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun minus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun plus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun point (Lspace/kscience/kmath/linear/GenericMatrixContext;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; - public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; - public static fun times (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; - public static fun unaryMinus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun unaryOperation (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun unaryOperationFunction (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/linear/GenericMatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; -} - public abstract interface class space/kscience/kmath/linear/InverseMatrixFeature : space/kscience/kmath/linear/MatrixFeature { public abstract fun getInverse ()Lspace/kscience/kmath/nd/Structure2D; } @@ -590,7 +457,7 @@ public final class space/kscience/kmath/linear/LFeature : space/kscience/kmath/l public final class space/kscience/kmath/linear/LinearAlgebraKt { public static final fun asMatrix (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/linear/VirtualMatrix; - public static final fun asPoint (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/structures/Buffer; + public static final fun asVector (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/structures/Buffer; } public abstract interface class space/kscience/kmath/linear/LinearSolver { @@ -603,9 +470,50 @@ public final class space/kscience/kmath/linear/LinearSolver$DefaultImpls { public static fun solve (Lspace/kscience/kmath/linear/LinearSolver;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; } +public abstract interface class space/kscience/kmath/linear/LinearSpace { + public static final field Companion Lspace/kscience/kmath/linear/LinearSpace$Companion; + public abstract fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D; + public abstract fun buildVector (ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun getElementAlgebra ()Lspace/kscience/kmath/operations/Ring; + public abstract fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public abstract fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public abstract fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; + public abstract fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public abstract fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; +} + +public final class space/kscience/kmath/linear/LinearSpace$Companion { + public final fun buffered (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/LinearSpace; + public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/LinearSpace$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/LinearSpace; + public final fun getReal ()Lspace/kscience/kmath/linear/LinearSpace; +} + +public final class space/kscience/kmath/linear/LinearSpace$DefaultImpls { + public static fun buildVector (Lspace/kscience/kmath/linear/LinearSpace;ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; + public static fun dot (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public static fun dot (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public static fun minus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public static fun minus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public static fun plus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public static fun plus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public static fun times (Lspace/kscience/kmath/linear/LinearSpace;Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public static fun times (Lspace/kscience/kmath/linear/LinearSpace;Ljava/lang/Object;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public static fun times (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; + public static fun times (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; + public static fun unaryMinus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public static fun unaryMinus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; +} + public final class space/kscience/kmath/linear/LupDecomposition : space/kscience/kmath/linear/DeterminantFeature, space/kscience/kmath/linear/LupDecompositionFeature { - public fun (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/operations/Field;Lspace/kscience/kmath/nd/Structure2D;[IZ)V - public final fun getContext ()Lspace/kscience/kmath/linear/MatrixContext; + public fun (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/operations/Field;Lspace/kscience/kmath/nd/Structure2D;[IZ)V + public final fun getContext ()Lspace/kscience/kmath/linear/LinearSpace; public fun getDeterminant ()Ljava/lang/Object; public final fun getElementContext ()Lspace/kscience/kmath/operations/Field; public fun getL ()Lspace/kscience/kmath/nd/Structure2D; @@ -622,57 +530,27 @@ public abstract interface class space/kscience/kmath/linear/LupDecompositionFeat } public final class space/kscience/kmath/linear/LupDecompositionKt { - public static final fun abs (Lspace/kscience/kmath/linear/GenericMatrixContext;Ljava/lang/Comparable;)Ljava/lang/Comparable; - public static final fun inverseWithLup (Lspace/kscience/kmath/linear/RealMatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static final fun lup (Lspace/kscience/kmath/linear/MatrixContext;Lkotlin/jvm/functions/Function2;Lspace/kscience/kmath/operations/Field;Lspace/kscience/kmath/nd/Structure2D;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/linear/LupDecomposition; - public static final fun lup (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/LupDecomposition; + public static final fun abs (Lspace/kscience/kmath/linear/LinearSpace;Ljava/lang/Comparable;)Ljava/lang/Comparable; + public static final fun inverseWithLup (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public static final fun lup (Lspace/kscience/kmath/linear/LinearSpace;Lkotlin/jvm/functions/Function2;Lspace/kscience/kmath/nd/Structure2D;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/linear/LupDecomposition; + public static final fun lup (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/LupDecomposition; + public static final fun solveWithLup (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static final fun solveWithLup (Lspace/kscience/kmath/linear/LupDecomposition;Lkotlin/jvm/functions/Function2;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static final fun solveWithLup (Lspace/kscience/kmath/linear/RealMatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; } public final class space/kscience/kmath/linear/MatrixBuilder { - public fun (II)V + public fun (Lspace/kscience/kmath/linear/LinearSpace;II)V public final fun getColumns ()I + public final fun getLinearSpace ()Lspace/kscience/kmath/linear/LinearSpace; public final fun getRows ()I public final fun invoke ([Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; } public final class space/kscience/kmath/linear/MatrixBuilderKt { - public static final fun build (Lspace/kscience/kmath/nd/Structure2D$Companion;II)Lspace/kscience/kmath/linear/MatrixBuilder; - public static final fun column (Lspace/kscience/kmath/nd/Structure2D$Companion;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; - public static final fun row (Lspace/kscience/kmath/nd/Structure2D$Companion;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; -} - -public abstract interface class space/kscience/kmath/linear/MatrixContext : space/kscience/kmath/operations/GroupOperations, space/kscience/kmath/operations/ScaleOperations { - public static final field Companion Lspace/kscience/kmath/linear/MatrixContext$Companion; - public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun point (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; -} - -public final class space/kscience/kmath/linear/MatrixContext$Companion { - public final fun buffered (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/GenericMatrixContext; - public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/MatrixContext$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/GenericMatrixContext; -} - -public final class space/kscience/kmath/linear/MatrixContext$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun binaryOperationFunction (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D; - public static fun div (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; - public static fun minus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun plus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun point (Lspace/kscience/kmath/linear/MatrixContext;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; - public static fun times (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun times (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun times (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; - public static fun unaryOperation (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun unaryOperationFunction (Lspace/kscience/kmath/linear/MatrixContext;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/linear/MatrixContext;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public static final fun column (Lspace/kscience/kmath/linear/LinearSpace;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/Structure2D; + public static final fun column (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; + public static final fun row (Lspace/kscience/kmath/linear/LinearSpace;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/Structure2D; + public static final fun row (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; } public abstract interface class space/kscience/kmath/linear/MatrixFeature { @@ -701,12 +579,11 @@ public final class space/kscience/kmath/linear/MatrixWrapper : space/kscience/km public final class space/kscience/kmath/linear/MatrixWrapperKt { public static final fun getOrigin (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static final fun one (Lspace/kscience/kmath/linear/GenericMatrixContext;II)Lspace/kscience/kmath/nd/Structure2D; + public static final fun one (Lspace/kscience/kmath/linear/LinearSpace;II)Lspace/kscience/kmath/nd/Structure2D; public static final fun plus (Lspace/kscience/kmath/nd/Structure2D;Ljava/util/Collection;)Lspace/kscience/kmath/linear/MatrixWrapper; public static final fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/linear/MatrixFeature;)Lspace/kscience/kmath/linear/MatrixWrapper; - public static final fun square (Lspace/kscience/kmath/nd/Structure2D$Companion;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; public static final fun transpose (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static final fun zero (Lspace/kscience/kmath/linear/GenericMatrixContext;II)Lspace/kscience/kmath/nd/Structure2D; + public static final fun zero (Lspace/kscience/kmath/linear/LinearSpace;II)Lspace/kscience/kmath/nd/Structure2D; } public final class space/kscience/kmath/linear/OrthogonalFeature : space/kscience/kmath/linear/MatrixFeature { @@ -718,52 +595,6 @@ public abstract interface class space/kscience/kmath/linear/QRDecompositionFeatu public abstract fun getR ()Lspace/kscience/kmath/nd/Structure2D; } -public final class space/kscience/kmath/linear/RealMatrixContext : space/kscience/kmath/linear/MatrixContext, space/kscience/kmath/operations/ScaleOperations { - public static final field INSTANCE Lspace/kscience/kmath/linear/RealMatrixContext; - public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun add (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; - public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public final fun one (II)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun point (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; - public fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun produce (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; - public fun scale (Lspace/kscience/kmath/nd/Structure2D;D)Lspace/kscience/kmath/linear/BufferMatrix; - public fun times (DLspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun times (Lspace/kscience/kmath/nd/Structure2D;D)Lspace/kscience/kmath/linear/BufferMatrix; - public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Number;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; - public final fun toBufferMatrix (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/linear/BufferMatrix; - public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; -} - -public final class space/kscience/kmath/linear/RealMatrixContextKt { - public static final fun getReal (Lspace/kscience/kmath/linear/MatrixContext$Companion;)Lspace/kscience/kmath/linear/RealMatrixContext; -} - public abstract interface class space/kscience/kmath/linear/SingularValueDecompositionFeature : space/kscience/kmath/linear/MatrixFeature { public abstract fun getS ()Lspace/kscience/kmath/nd/Structure2D; public abstract fun getSingularValues ()Lspace/kscience/kmath/structures/Buffer; @@ -784,41 +615,6 @@ public final class space/kscience/kmath/linear/UnitFeature : space/kscience/kmat public static final field INSTANCE Lspace/kscience/kmath/linear/UnitFeature; } -public abstract interface class space/kscience/kmath/linear/VectorSpace : space/kscience/kmath/operations/Group, space/kscience/kmath/operations/ScaleOperations { - public static final field Companion Lspace/kscience/kmath/linear/VectorSpace$Companion; - public abstract fun add (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun getAlgebra ()Lspace/kscience/kmath/operations/Group; - public abstract fun getSize ()I - public abstract fun getZero ()Lspace/kscience/kmath/structures/Buffer; - public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun scale (Lspace/kscience/kmath/structures/Buffer;D)Lspace/kscience/kmath/structures/Buffer; - public abstract fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; -} - -public final class space/kscience/kmath/linear/VectorSpace$Companion { - public final fun buffered (ILspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferVectorSpace; - public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/VectorSpace$Companion;ILspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/BufferVectorSpace; - public final fun real (I)Lspace/kscience/kmath/linear/BufferVectorSpace; -} - -public final class space/kscience/kmath/linear/VectorSpace$DefaultImpls { - public static fun add (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun binaryOperation (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun binaryOperationFunction (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; - public static fun div (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public static fun getZero (Lspace/kscience/kmath/linear/VectorSpace;)Lspace/kscience/kmath/structures/Buffer; - public static fun minus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun plus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun scale (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;D)Lspace/kscience/kmath/structures/Buffer; - public static fun times (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun times (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public static fun unaryMinus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun unaryOperation (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun unaryOperationFunction (Lspace/kscience/kmath/linear/VectorSpace;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/linear/VectorSpace;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; -} - public final class space/kscience/kmath/linear/VirtualMatrix : space/kscience/kmath/nd/Structure2D { public fun (IILkotlin/jvm/functions/Function2;)V public fun elements ()Lkotlin/sequences/Sequence; @@ -1147,10 +943,10 @@ public abstract interface class space/kscience/kmath/nd/NDStructure { public final class space/kscience/kmath/nd/NDStructure$Companion { public final fun auto (Lkotlin/reflect/KClass;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; public final fun auto (Lkotlin/reflect/KClass;[ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; - public final fun build (Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; - public final fun build ([ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; - public static synthetic fun build$default (Lspace/kscience/kmath/nd/NDStructure$Companion;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer; - public static synthetic fun build$default (Lspace/kscience/kmath/nd/NDStructure$Companion;[ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer; + public final fun buffered (Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; + public final fun buffered ([ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; + public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/NDStructure$Companion;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer; + public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/NDStructure$Companion;[ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer; public final fun contentEquals (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Z } @@ -1314,7 +1110,6 @@ public abstract interface class space/kscience/kmath/nd/Structure2D : space/ksci } public final class space/kscience/kmath/nd/Structure2D$Companion { - public final fun real (IILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferMatrix; } public final class space/kscience/kmath/nd/Structure2D$DefaultImpls { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt index 6814cb561..0a7f280bc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt @@ -16,19 +16,13 @@ public class MatrixBuilder>( //TODO add specific matrix builder functions like diagonal, etc } +/** + * Create a matrix builder with given number of rows and columns + */ @UnstableKMathAPI public fun > LinearSpace.matrix(rows: Int, columns: Int): MatrixBuilder = MatrixBuilder(this, rows, columns) -/** - * Build a square matrix from given elements. - */ -@UnstableKMathAPI -public fun LinearSpace>.square(vararg elements: T): Matrix { - val size: Int = kotlin.math.sqrt(elements.size.toDouble()).toInt() - return matrix(size,size)(*elements) -} - @UnstableKMathAPI public fun LinearSpace>.vector(vararg elements: T): Vector { return buildVector(elements.size) { elements[it] } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt index 11699ce2f..7f0451946 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.linear +import space.kscience.kmath.nd.NDStructure + /** * The matrix where each element is evaluated each time when is being accessed. * @@ -17,12 +19,8 @@ public class VirtualMatrix( override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is Matrix<*>) return false - - if (rowNum != other.rowNum) return false - if (colNum != other.colNum) return false - - return elements().all { (index, value) -> value == other[index] } + if (other !is NDStructure<*>) return false + return NDStructure.contentEquals(this, other) } override fun hashCode(): Int { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 0098eeb3b..09c830646 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -1,7 +1,9 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.VirtualBuffer +import kotlin.reflect.KClass /** * A structure that is guaranteed to be two-dimensional. @@ -58,7 +60,7 @@ public interface Structure2D : NDStructure { /** * A 2D wrapper for nd-structure */ -private inline class Structure2DWrapper(val structure: NDStructure) : Structure2D { +private class Structure2DWrapper(val structure: NDStructure) : Structure2D { override val shape: IntArray get() = structure.shape override val rowNum: Int get() = shape[0] @@ -66,7 +68,14 @@ private inline class Structure2DWrapper(val structure: NDStructure) : Stru override operator fun get(i: Int, j: Int): T = structure[i, j] + @UnstableKMathAPI + override fun getFeature(type: KClass): F? = structure.getFeature(type) + override fun elements(): Sequence> = structure.elements() + + override fun equals(other: Any?): Boolean = structure == other + + override fun hashCode(): Int = structure.hashCode() } /** diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt index 53cdd4522..097703f49 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt @@ -1,10 +1,12 @@ package space.kscience.kmath.linear +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.NDStructure import space.kscience.kmath.nd.as2D import kotlin.test.Test import kotlin.test.assertEquals +@UnstableKMathAPI @Suppress("UNUSED_VARIABLE") class MatrixTest { @Test diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt index 802849a1e..704f91998 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt @@ -1,8 +1,10 @@ package space.kscience.kmath.linear +import space.kscience.kmath.misc.UnstableKMathAPI import kotlin.test.Test import kotlin.test.assertEquals +@UnstableKMathAPI class RealLUSolverTest { @Test @@ -15,7 +17,7 @@ class RealLUSolverTest { @Test fun testDecomposition() { LinearSpace.real.run { - val matrix = square( + val matrix = matrix(2,2)( 3.0, 1.0, 1.0, 3.0 ) @@ -31,14 +33,14 @@ class RealLUSolverTest { @Test fun testInvert() { - val matrix = LinearSpace.real.square( + val matrix = LinearSpace.real.matrix(2,2)( 3.0, 1.0, 1.0, 3.0 ) val inverted = LinearSpace.real.inverseWithLup(matrix) - val expected = LinearSpace.real.square( + val expected = LinearSpace.real.matrix(2,2)( 0.375, -0.125, -0.125, 0.375 ) diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt index 640615cc9..76c73ab16 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt @@ -25,6 +25,10 @@ public typealias RealMatrix = Matrix public fun realMatrix(rowNum: Int, colNum: Int, initializer: RealField.(i: Int, j: Int) -> Double): RealMatrix = LinearSpace.real.buildMatrix(rowNum, colNum, initializer) +@OptIn(UnstableKMathAPI::class) +public fun realMatrix(rowNum: Int, colNum: Int): MatrixBuilder = + LinearSpace.real.matrix(rowNum, colNum) + public fun Array.toMatrix(): RealMatrix { return LinearSpace.real.buildMatrix(size, this[0].size) { row, col -> this@toMatrix[row][col] } } diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt index 6ab11b03b..06135598e 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt @@ -9,6 +9,7 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue +@UnstableKMathAPI internal class RealMatrixTest { @Test fun testSum() { @@ -30,11 +31,11 @@ internal class RealMatrixTest { @Test fun testRepeatStackVertical() { - val matrix1 = LinearSpace.real.matrix(2, 3)( + val matrix1 = realMatrix(2, 3)( 1.0, 0.0, 0.0, 0.0, 1.0, 2.0 ) - val matrix2 = LinearSpace.real.matrix(6, 3)( + val matrix2 = realMatrix(6, 3)( 1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 1.0, 0.0, 0.0, @@ -47,7 +48,7 @@ internal class RealMatrixTest { @Test fun testMatrixAndDouble() { - val matrix1 = LinearSpace.real.matrix(2, 3)( + val matrix1 = realMatrix(2, 3)( 1.0, 0.0, 3.0, 4.0, 6.0, 2.0 ) @@ -61,13 +62,13 @@ internal class RealMatrixTest { @Test fun testDoubleAndMatrix() { - val matrix1 = LinearSpace.real.matrix(2, 3)( + val matrix1 = realMatrix(2, 3)( 1.0, 0.0, 3.0, 4.0, 6.0, 2.0 ) val matrix2 = 20.0 - (10.0 + (5.0 * matrix1)) //val matrix2 = 10.0 + (5.0 * matrix1) - val expectedResult = LinearSpace.real.matrix(2, 3)( + val expectedResult = realMatrix(2, 3)( 5.0, 10.0, -5.0, -10.0, -20.0, 0.0 ) @@ -76,15 +77,15 @@ internal class RealMatrixTest { @Test fun testSquareAndPower() { - val matrix1 = LinearSpace.real.matrix(2, 3)( + val matrix1 = realMatrix(2, 3)( -1.0, 0.0, 3.0, 4.0, -6.0, -2.0 ) - val matrix2 = LinearSpace.real.matrix(2, 3)( + val matrix2 = realMatrix(2, 3)( 1.0, 0.0, 9.0, 16.0, 36.0, 4.0 ) - val matrix3 = LinearSpace.real.matrix(2, 3)( + val matrix3 = realMatrix(2, 3)( -1.0, 0.0, 27.0, 64.0, -216.0, -8.0 ) @@ -95,16 +96,16 @@ internal class RealMatrixTest { @OptIn(UnstableKMathAPI::class) @Test fun testTwoMatrixOperations() { - val matrix1 = LinearSpace.real.matrix(2, 3)( + val matrix1 = realMatrix(2, 3)( -1.0, 0.0, 3.0, 4.0, -6.0, 7.0 ) - val matrix2 = LinearSpace.real.matrix(2, 3)( + val matrix2 = realMatrix(2, 3)( 1.0, 0.0, 3.0, 4.0, 6.0, -2.0 ) val result = matrix1 * matrix2 + matrix1 - matrix2 - val expectedResult = LinearSpace.real.matrix(2, 3)( + val expectedResult = realMatrix(2, 3)( -3.0, 0.0, 9.0, 16.0, -48.0, -5.0 ) @@ -113,16 +114,16 @@ internal class RealMatrixTest { @Test fun testColumnOperations() { - val matrix1 = LinearSpace.real.matrix(2, 4)( + val matrix1 = realMatrix(2, 4)( -1.0, 0.0, 3.0, 15.0, 4.0, -6.0, 7.0, -11.0 ) - val matrix2 = LinearSpace.real.matrix(2, 5)( + val matrix2 = realMatrix(2, 5)( -1.0, 0.0, 3.0, 15.0, -1.0, 4.0, -6.0, 7.0, -11.0, 4.0 ) - val col1 = LinearSpace.real.matrix(2, 1)(0.0, -6.0) - val cols1to2 = LinearSpace.real.matrix(2, 2)( + val col1 = realMatrix(2, 1)(0.0, -6.0) + val cols1to2 = realMatrix(2, 2)( 0.0, 3.0, -6.0, 7.0 ) From 384415dc98ae27125f894798057f6052103e2594 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sat, 13 Mar 2021 19:16:13 +0000 Subject: [PATCH 068/393] utils module for tensors --- .../kscience/kmath/tensors/BufferedTensor.kt | 28 ++++-- .../kmath/tensors/RealTensorAlgebra.kt | 63 ------------ .../kscience/kmath/tensors/TensorAlgebra.kt | 46 +-------- .../kscience/kmath/tensors/TensorStrides.kt | 6 +- .../space/kscience/kmath/tensors/utils.kt | 96 +++++++++++++++++++ .../kmath/tensors/TestRealTensorAlgebra.kt | 8 +- 6 files changed, 124 insertions(+), 123 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index 9ffe2db61..29605024d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -1,9 +1,8 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.linear.BufferMatrix import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.* -import space.kscience.kmath.structures.BufferAccessor2D + public open class BufferedTensor( override val shape: IntArray, @@ -15,13 +14,13 @@ public open class BufferedTensor( buffer ) { - public operator fun get(i: Int, j: Int): T{ - check(this.dimension == 2) {"Not matrix"} - return this[intArrayOf(i, j)] + public operator fun get(i: Int, j: Int): T { + check(this.dimension == 2) { "Not matrix" } + return this[intArrayOf(i, j)] } - public operator fun set(i: Int, j: Int, value: T): Unit{ - check(this.dimension == 2) {"Not matrix"} + public operator fun set(i: Int, j: Int, value: T): Unit { + check(this.dimension == 2) { "Not matrix" } this[intArrayOf(i, j)] = value } @@ -31,3 +30,18 @@ public class IntTensor( shape: IntArray, buffer: IntArray ) : BufferedTensor(shape, IntBuffer(buffer)) + +public class LongTensor( + shape: IntArray, + buffer: LongArray +) : BufferedTensor(shape, LongBuffer(buffer)) + +public class FloatTensor( + shape: IntArray, + buffer: FloatArray +) : BufferedTensor(shape, FloatBuffer(buffer)) + +public class RealTensor( + shape: IntArray, + buffer: DoubleArray +) : BufferedTensor(shape, RealBuffer(buffer)) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index f91f44519..b3e54f077 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -6,11 +6,6 @@ import kotlin.math.abs import kotlin.math.max -public class RealTensor( - shape: IntArray, - buffer: DoubleArray -) : BufferedTensor(shape, RealBuffer(buffer)) - public class RealTensorAlgebra : TensorPartialDivisionAlgebra { override fun RealTensor.value(): Double { @@ -54,64 +49,6 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { - val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) - val n = totalShape.reduce{ acc, i -> acc * i } - - val res = ArrayList(0) - for (tensor in tensors) { - val resTensor = RealTensor(totalShape, DoubleArray(n)) - - for (linearIndex in 0 until n) { - val totalMultiIndex = resTensor.strides.index(linearIndex) - val curMultiIndex = tensor.shape.copyOf() - - val offset = totalMultiIndex.size - curMultiIndex.size - - for (i in curMultiIndex.indices) { - if (curMultiIndex[i] != 1) { - curMultiIndex[i] = totalMultiIndex[i + offset] - } else { - curMultiIndex[i] = 0 - } - } - - val curLinearIndex = tensor.strides.offset(curMultiIndex) - resTensor.buffer.array[linearIndex] = tensor.buffer.array[curLinearIndex] - } - res.add(resTensor) - } - - return res - } override fun Double.plus(other: RealTensor): RealTensor { val resBuffer = DoubleArray(other.buffer.size) { i -> diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index ec257e45c..280acf8ea 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -13,9 +13,6 @@ public interface TensorAlgebra> { public fun TensorType.copy(): TensorType - public fun broadcastShapes(vararg shapes: IntArray): IntArray - public fun broadcastTensors(vararg tensors: RealTensor): List - public operator fun T.plus(other: TensorType): TensorType public operator fun TensorType.plus(value: T): TensorType public operator fun TensorType.plus(other: TensorType): TensorType @@ -87,45 +84,4 @@ public interface TensorPartialDivisionAlgebra //https://pytorch.org/docs/stable/generated/torch.symeig.html public fun TensorType.symEig(eigenvectors: Boolean = true): Pair -} - -public inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkShapeCompatible( - a: TensorType, b: TensorType -): Unit = - check(a.shape contentEquals b.shape) { - "Tensors must be of identical shape" - } - -public inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkDot(a: TensorType, b: TensorType): Unit { - val sa = a.shape - val sb = b.shape - val na = sa.size - val nb = sb.size - var status: Boolean - if (nb == 1) { - status = sa.last() == sb[0] - } else { - status = sa.last() == sb[nb - 2] - if ((na > 2) and (nb > 2)) { - status = status and - (sa.take(nb - 2).toIntArray() contentEquals sb.take(nb - 2).toIntArray()) - } - } - check(status) { "Incompatible shapes $sa and $sb for dot product" } -} - -public inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkTranspose(dim: Int, i: Int, j: Int): Unit = - check((i < dim) and (j < dim)) { - "Cannot transpose $i to $j for a tensor of dim $dim" - } - -public inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = - check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt index d6a6f5f16..d1d1204b4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStrides.kt @@ -5,7 +5,7 @@ import space.kscience.kmath.nd.offsetFromIndex import kotlin.math.max -public inline fun stridesFromShape(shape: IntArray): IntArray { +internal inline fun stridesFromShape(shape: IntArray): IntArray { val nDim = shape.size val res = IntArray(nDim) if (nDim == 0) @@ -22,7 +22,7 @@ public inline fun stridesFromShape(shape: IntArray): IntArray { } -public inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { +internal inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { val res = IntArray(nDim) var current = offset var strideIndex = 0 @@ -35,7 +35,7 @@ public inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): In return res } -public inline fun nextIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { +internal inline fun nextIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { val res = index.copyOf() var current = nDim - 1 var carry = 0 diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt new file mode 100644 index 000000000..65409bb15 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt @@ -0,0 +1,96 @@ +package space.kscience.kmath.tensors + +import space.kscience.kmath.structures.array +import kotlin.math.max + + +internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { + var totalDim = 0 + for (shape in shapes) { + totalDim = max(totalDim, shape.size) + } + + val totalShape = IntArray(totalDim) { 0 } + for (shape in shapes) { + for (i in shape.indices) { + val curDim = shape[i] + val offset = totalDim - shape.size + totalShape[i + offset] = max(totalShape[i + offset], curDim) + } + } + + for (shape in shapes) { + for (i in shape.indices) { + val curDim = shape[i] + val offset = totalDim - shape.size + if (curDim != 1 && totalShape[i + offset] != curDim) { + throw RuntimeException("Shapes are not compatible and cannot be broadcast") + } + } + } + + return totalShape +} + +internal inline fun broadcastTensors(vararg tensors: RealTensor): List { + val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) + val n = totalShape.reduce { acc, i -> acc * i } + + val res = ArrayList(0) + for (tensor in tensors) { + val resTensor = RealTensor(totalShape, DoubleArray(n)) + + for (linearIndex in 0 until n) { + val totalMultiIndex = resTensor.strides.index(linearIndex) + val curMultiIndex = tensor.shape.copyOf() + + val offset = totalMultiIndex.size - curMultiIndex.size + + for (i in curMultiIndex.indices) { + if (curMultiIndex[i] != 1) { + curMultiIndex[i] = totalMultiIndex[i + offset] + } else { + curMultiIndex[i] = 0 + } + } + + val curLinearIndex = tensor.strides.offset(curMultiIndex) + resTensor.buffer.array[linearIndex] = tensor.buffer.array[curLinearIndex] + } + res.add(resTensor) + } + + return res +} + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkDot(a: TensorType, b: TensorType): Unit { + val sa = a.shape + val sb = b.shape + val na = sa.size + val nb = sb.size + var status: Boolean + if (nb == 1) { + status = sa.last() == sb[0] + } else { + status = sa.last() == sb[nb - 2] + if ((na > 2) and (nb > 2)) { + status = status and + (sa.take(nb - 2).toIntArray() contentEquals sb.take(nb - 2).toIntArray()) + } + } + check(status) { "Incompatible shapes $sa and $sb for dot product" } +} + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkTranspose(dim: Int, i: Int, j: Int): Unit = + check((i < dim) and (j < dim)) { + "Cannot transpose $i to $j for a tensor of dim $dim" + } + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = + check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index c9fd6bb3a..7c27f5fa9 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -2,8 +2,6 @@ package space.kscience.kmath.tensors import space.kscience.kmath.structures.array import kotlin.test.Test -import kotlin.test.assertFails -import kotlin.test.assertFailsWith import kotlin.test.assertTrue class TestRealTensorAlgebra { @@ -51,11 +49,11 @@ class TestRealTensorAlgebra { @Test fun broadcastShapes() = RealTensorAlgebra { - assertTrue(this.broadcastShapes( + assertTrue(broadcastShapes( intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) ) contentEquals intArrayOf(1, 2, 3)) - assertTrue(this.broadcastShapes( + assertTrue(broadcastShapes( intArrayOf(6, 7), intArrayOf(5, 6, 1), intArrayOf(7,), intArrayOf(5, 1, 7) ) contentEquals intArrayOf(5, 6, 7)) } @@ -66,7 +64,7 @@ class TestRealTensorAlgebra { val tensor2 = RealTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) - val res = this.broadcastTensors(tensor1, tensor2, tensor3) + val res = broadcastTensors(tensor1, tensor2, tensor3) assertTrue(res[0].shape contentEquals intArrayOf(1, 2, 3)) assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) From 0aa73cd48fd0aa517189987ecbb0f011114d9a3e Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 14 Mar 2021 09:43:22 +0300 Subject: [PATCH 069/393] Vector space refactor (optimization) --- examples/build.gradle.kts | 8 ++ .../kscience/kmath/benchmarks/DotBenchmark.kt | 17 ++-- .../ExpressionsInterpretersBenchmark.kt | 4 +- ...Benchmark.kt => MatrixInverseBenchmark.kt} | 13 +-- .../kmath/benchmarks/ViktorLogBenchmark.kt | 4 +- .../space/kscience/kmath/ast/MstAlgebra.kt | 6 +- kmath-core/api/kmath-core.api | 44 +++++++--- .../kscience/kmath/linear/LinearSpace.kt | 20 ++--- .../kmath/linear/LinearSpaceOverNd.kt | 85 +++++++++++++++++++ .../kscience/kmath/nd/BufferNDAlgebra.kt | 8 +- .../space/kscience/kmath/nd/Structure1D.kt | 6 +- .../space/kscience/kmath/nd/Structure2D.kt | 25 +++--- .../kmath/structures/BufferAccessor2D.kt | 4 +- .../kmath/structures/bufferOperation.kt | 7 ++ .../kscience/kmath/linear/RealLUSolverTest.kt | 4 +- .../kscience/kmath/ejml/EjmlLinearSpace.kt | 8 +- .../kotlin/space/kscience/kmath/real/dot.kt | 2 +- 17 files changed, 183 insertions(+), 82 deletions(-) rename examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/{LinearAlgebraBenchmark.kt => MatrixInverseBenchmark.kt} (75%) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpaceOverNd.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 77152dc0a..0301e4d67 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -92,6 +92,14 @@ benchmark { iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds include("ExpressionsInterpretersBenchmark") } + + configurations.register("matrixInverse") { + warmups = 1 // number of warmup iterations + iterations = 3 // number of iterations + iterationTime = 500 // time in seconds per iteration + iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + include("MatrixInverseBenchmark") + } } kotlin.sourceSets.all { diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt index 8fb0c284e..dbf373929 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt @@ -6,12 +6,9 @@ import kotlinx.benchmark.Scope import kotlinx.benchmark.State import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.ejml.EjmlLinearSpace -import space.kscience.kmath.linear.BufferLinearSpace -import space.kscience.kmath.linear.Matrix -import space.kscience.kmath.linear.RealLinearSpace +import space.kscience.kmath.linear.LinearSpace +import space.kscience.kmath.linear.invoke import space.kscience.kmath.operations.RealField -import space.kscience.kmath.operations.invoke -import space.kscience.kmath.structures.Buffer import kotlin.random.Random @State(Scope.Benchmark) @@ -21,8 +18,8 @@ internal class DotBenchmark { const val dim = 1000 //creating invertible matrix - val matrix1 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } - val matrix2 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } + val matrix1 = LinearSpace.real.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } + val matrix2 = LinearSpace.real.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } val cmMatrix1 = CMLinearSpace { matrix1.toCM() } val cmMatrix2 = CMLinearSpace { matrix2.toCM() } @@ -33,7 +30,7 @@ internal class DotBenchmark { @Benchmark fun cmDot(blackhole: Blackhole) { - CMLinearSpace { + CMLinearSpace.run { blackhole.consume(cmMatrix1 dot cmMatrix2) } } @@ -54,14 +51,14 @@ internal class DotBenchmark { @Benchmark fun bufferedDot(blackhole: Blackhole) { - BufferLinearSpace(RealField, Buffer.Companion::real).invoke { + LinearSpace.auto(RealField).invoke { blackhole.consume(matrix1 dot matrix2) } } @Benchmark fun realDot(blackhole: Blackhole) { - RealLinearSpace { + LinearSpace.real { blackhole.consume(matrix1 dot matrix2) } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index 9c150f074..e5cfbf9f6 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -30,7 +30,7 @@ internal class ExpressionsInterpretersBenchmark { fun mstExpression(blackhole: Blackhole) { val expr = algebra.mstInField { val x = bindSymbol(x) - x * 2.0 + 2.0 / x - 16.0 + x * 2.0 + number(2.0) / x - 16.0 } invokeAndSum(expr, blackhole) @@ -40,7 +40,7 @@ internal class ExpressionsInterpretersBenchmark { fun asmExpression(blackhole: Blackhole) { val expr = algebra.mstInField { val x = bindSymbol(x) - x * 2.0 + 2.0 / x - 16.0 + x * 2.0 + number(2.0) / x - 16.0 }.compile() invokeAndSum(expr, blackhole) diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt similarity index 75% rename from examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt rename to examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt index 85759d93c..7aa8ac975 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/LinearAlgebraBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt @@ -9,21 +9,22 @@ import space.kscience.kmath.commons.linear.inverse import space.kscience.kmath.ejml.EjmlLinearSpace import space.kscience.kmath.ejml.inverse import space.kscience.kmath.linear.LinearSpace -import space.kscience.kmath.linear.Matrix import space.kscience.kmath.linear.inverseWithLup -import space.kscience.kmath.linear.real +import space.kscience.kmath.linear.invoke import kotlin.random.Random @State(Scope.Benchmark) -internal class LinearAlgebraBenchmark { +internal class MatrixInverseBenchmark { companion object { val random = Random(1224) const val dim = 100 + private val space = LinearSpace.real + //creating invertible matrix - val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } - val l = Matrix.real(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 } - val matrix = l dot u + val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } + val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 } + val matrix = space { l dot u } } @Benchmark diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt index c48c86af9..0036b615c 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt @@ -15,7 +15,7 @@ import space.kscience.kmath.viktor.ViktorNDField internal class ViktorLogBenchmark { @Benchmark fun realFieldLog(blackhole: Blackhole) { - with(realField) { + with(realNdField) { val fortyTwo = produce { 42.0 } var res = one repeat(n) { res = ln(fortyTwo) } @@ -47,7 +47,7 @@ internal class ViktorLogBenchmark { // automatically build context most suited for given type. private val autoField = NDAlgebra.auto(RealField, dim, dim) - private val realField = NDAlgebra.real(dim, dim) + private val realNdField = NDAlgebra.real(dim, dim) private val viktorField = ViktorNDField(intArrayOf(dim, dim)) } } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt index 16fdfbeac..5ed39687b 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt @@ -54,7 +54,7 @@ public object MstRing : Ring, NumbersAddOperations, ScaleOperations, NumbersAddOperations, ScaleOperations< public override val one: MST.Numeric get() = MstRing.one - public override fun bindSymbol(value: String): MST.Symbolic = MstRing.bindSymbol(value) + public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value) public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b) @@ -112,7 +112,7 @@ public object MstExtendedField : ExtendedField, NumericAlgebra { public override val zero: MST.Numeric get() = MstField.zero public override val one: MST.Numeric get() = MstField.one - public override fun bindSymbol(value: String): MST.Symbolic = MstField.bindSymbol(value) + public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value) public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg) public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index c1f8d5ec5..38da35d6c 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -496,7 +496,6 @@ public final class space/kscience/kmath/linear/LinearSpace$Companion { } public final class space/kscience/kmath/linear/LinearSpace$DefaultImpls { - public static fun buildVector (Lspace/kscience/kmath/linear/LinearSpace;ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; public static fun dot (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static fun dot (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static fun minus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; @@ -511,6 +510,29 @@ public final class space/kscience/kmath/linear/LinearSpace$DefaultImpls { public static fun unaryMinus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; } +public final class space/kscience/kmath/linear/LinearSpaceKt { + public static final fun invoke (Lspace/kscience/kmath/linear/LinearSpace;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/linear/LinearSpaceOverNd : space/kscience/kmath/linear/LinearSpace { + public fun (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V + public fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D; + public fun buildVector (ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; + public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun getElementAlgebra ()Lspace/kscience/kmath/operations/Ring; + public fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun times (Ljava/lang/Object;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; + public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; + public fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; +} + public final class space/kscience/kmath/linear/LupDecomposition : space/kscience/kmath/linear/DeterminantFeature, space/kscience/kmath/linear/LupDecompositionFeature { public fun (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/operations/Field;Lspace/kscience/kmath/nd/Structure2D;[IZ)V public final fun getContext ()Lspace/kscience/kmath/linear/LinearSpace; @@ -566,12 +588,12 @@ public final class space/kscience/kmath/linear/MatrixWrapper : space/kscience/km public fun get (II)Ljava/lang/Object; public fun get ([I)Ljava/lang/Object; public fun getColNum ()I - public fun getColumns ()Lspace/kscience/kmath/structures/Buffer; + public fun getColumns ()Ljava/util/List; public fun getDimension ()I public final fun getFeatures ()Ljava/util/Set; public final fun getOrigin ()Lspace/kscience/kmath/nd/Structure2D; public fun getRowNum ()I - public fun getRows ()Lspace/kscience/kmath/structures/Buffer; + public fun getRows ()Ljava/util/List; public fun getShape ()[I public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -622,11 +644,11 @@ public final class space/kscience/kmath/linear/VirtualMatrix : space/kscience/km public fun get (II)Ljava/lang/Object; public fun get ([I)Ljava/lang/Object; public fun getColNum ()I - public fun getColumns ()Lspace/kscience/kmath/structures/Buffer; + public fun getColumns ()Ljava/util/List; public fun getDimension ()I public final fun getGenerator ()Lkotlin/jvm/functions/Function2; public fun getRowNum ()I - public fun getRows ()Lspace/kscience/kmath/structures/Buffer; + public fun getRows ()Ljava/util/List; public fun getShape ()[I public fun hashCode ()I } @@ -678,11 +700,11 @@ public final class space/kscience/kmath/nd/BufferNDAlgebra$DefaultImpls { public final class space/kscience/kmath/nd/BufferNDAlgebraKt { public static final fun field (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDField; + public static final fun group (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDGroup; public static final fun ndField (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun ndGroup (Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun ndRing (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun ndSpace (Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun ring (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDRing; - public static final fun space (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDGroup; } public class space/kscience/kmath/nd/BufferedNDField : space/kscience/kmath/nd/BufferedNDRing, space/kscience/kmath/nd/NDField { @@ -1103,9 +1125,9 @@ public abstract interface class space/kscience/kmath/nd/Structure2D : space/ksci public abstract fun get (II)Ljava/lang/Object; public abstract fun get ([I)Ljava/lang/Object; public abstract fun getColNum ()I - public abstract fun getColumns ()Lspace/kscience/kmath/structures/Buffer; + public abstract fun getColumns ()Ljava/util/List; public abstract fun getRowNum ()I - public abstract fun getRows ()Lspace/kscience/kmath/structures/Buffer; + public abstract fun getRows ()Ljava/util/List; public abstract fun getShape ()[I } @@ -1115,9 +1137,9 @@ public final class space/kscience/kmath/nd/Structure2D$Companion { public final class space/kscience/kmath/nd/Structure2D$DefaultImpls { public static fun elements (Lspace/kscience/kmath/nd/Structure2D;)Lkotlin/sequences/Sequence; public static fun get (Lspace/kscience/kmath/nd/Structure2D;[I)Ljava/lang/Object; - public static fun getColumns (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/structures/Buffer; + public static fun getColumns (Lspace/kscience/kmath/nd/Structure2D;)Ljava/util/List; public static fun getDimension (Lspace/kscience/kmath/nd/Structure2D;)I - public static fun getRows (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/structures/Buffer; + public static fun getRows (Lspace/kscience/kmath/nd/Structure2D;)Ljava/util/List; public static fun getShape (Lspace/kscience/kmath/nd/Structure2D;)[I } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 4a9d2c9b3..b0331bdea 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -33,8 +33,7 @@ public interface LinearSpace> { /** * Produces a point compatible with matrix space (and possibly optimized for it). */ - public fun buildVector(size: Int, initializer: A.(Int) -> T): Vector = - buildMatrix(1, size) { _, j -> initializer(j) }.as1D() + public fun buildVector(size: Int, initializer: A.(Int) -> T): Vector public operator fun Matrix.unaryMinus(): Matrix = buildMatrix(rowNum, colNum) { i, j -> -get(i, j) @@ -154,7 +153,7 @@ public interface LinearSpace> { /** * Gets a feature from the matrix. This function may return some additional features to - * [space.kscience.kmath.nd.NDStructure.getFeature]. + * [group.kscience.kmath.nd.NDStructure.getFeature]. * * @param F the type of feature. * @param m the matrix. @@ -172,16 +171,7 @@ public interface LinearSpace> { public fun > buffered( algebra: A, bufferFactory: BufferFactory = Buffer.Companion::boxing, - ): LinearSpace = object : LinearSpace { - override val elementAlgebra: A = algebra - - override fun buildMatrix( - rows: Int, columns: Int, - initializer: A.(i: Int, j: Int) -> T, - ): Matrix = NDStructure.buffered(intArrayOf(rows, columns), bufferFactory) { (i, j) -> - algebra.initializer(i, j) - }.as2D() - } + ): LinearSpace = LinearSpaceOverNd(algebra,bufferFactory) public val real: LinearSpace = buffered(RealField, Buffer.Companion::real) @@ -193,9 +183,11 @@ public interface LinearSpace> { } } +public operator fun , R> LS.invoke(block: LS.() -> R): R = run(block) + /** * Gets a feature from the matrix. This function may return some additional features to - * [space.kscience.kmath.nd.NDStructure.getFeature]. + * [group.kscience.kmath.nd.NDStructure.getFeature]. * * @param T the type of items in the matrices. * @param M the type of operated matrices. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpaceOverNd.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpaceOverNd.kt new file mode 100644 index 000000000..6a82f37ec --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpaceOverNd.kt @@ -0,0 +1,85 @@ +package space.kscience.kmath.linear + +import space.kscience.kmath.nd.* +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferFactory +import space.kscience.kmath.structures.VirtualBuffer +import space.kscience.kmath.structures.indices + + +public class LinearSpaceOverNd>( + override val elementAlgebra: A, + private val bufferFactory: BufferFactory, +) : LinearSpace { + + private fun ndRing( + rows: Int, + cols: Int, + ): BufferedNDRing = NDAlgebra.ring(elementAlgebra, bufferFactory, rows, cols) + + override fun buildMatrix(rows: Int, columns: Int, initializer: A.(i: Int, j: Int) -> T): Matrix = + ndRing(rows, columns).produce { (i, j) -> elementAlgebra.initializer(i, j) }.as2D() + + override fun buildVector(size: Int, initializer: A.(Int) -> T): Vector = + bufferFactory(size) { elementAlgebra.initializer(it) } + + override fun Matrix.unaryMinus(): Matrix = ndRing(rowNum, colNum).run { + unwrap().map { -it }.as2D() + } + + override fun Matrix.plus(other: Matrix): Matrix = ndRing(rowNum, colNum).run { + require(shape.contentEquals(other.shape)) { "Shape mismatch on Matrix::plus. Expected $shape but found ${other.shape}" } + unwrap().plus(other.unwrap()).as2D() + } + + override fun Matrix.minus(other: Matrix): Matrix = ndRing(rowNum, colNum).run { + require(shape.contentEquals(other.shape)) { "Shape mismatch on Matrix::plus. Expected $shape but found ${other.shape}" } + unwrap().minus(other.unwrap()).as2D() + } + + private fun Buffer.linearize() = if (this is VirtualBuffer) { + buildVector(size) { get(it) } + } else { + this + } + + override fun Matrix.dot(other: Matrix): Matrix { + require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } + return elementAlgebra { + val rows = this@dot.rows.map{it.linearize()} + val columns = other.columns.map { it.linearize() } + //TODO optimize buffers + buildMatrix(rowNum, other.colNum) { i, j -> + val r = rows[i] + val c = columns[j] + var res = zero + for (l in r.indices) { + res += r[l] * c[l] + } + res + } + } + } + + override fun Matrix.dot(vector: Vector): Vector { + require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } + return elementAlgebra { + val rows = this@dot.rows + //TODO optimize buffers + buildVector(rowNum) { i -> + val r = rows[i] + var res = zero + for (j in r.indices) { + res += r[j] * vector[j] + } + res + } + } + } + + override fun Matrix.times(value: T): Matrix = ndRing(rowNum, colNum).run { + unwrap().map { it * value }.as2D() + } +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt index 58d1ea7b1..bce3a0830 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt @@ -79,20 +79,20 @@ public open class BufferedNDField>( override fun scale(a: NDStructure, value: Double): NDStructure = a.map { it * value } } -// space factories -public fun > NDAlgebra.Companion.space( +// group factories +public fun > NDAlgebra.Companion.group( space: A, bufferFactory: BufferFactory, vararg shape: Int, ): BufferedNDGroup = BufferedNDGroup(shape, space, bufferFactory) -public inline fun , R> A.ndSpace( +public inline fun , R> A.ndGroup( noinline bufferFactory: BufferFactory, vararg shape: Int, action: BufferedNDGroup.() -> R, ): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return NDAlgebra.space(this, bufferFactory, *shape).run(action) + return NDAlgebra.group(this, bufferFactory, *shape).run(action) } //ring factories diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index c54bfeed9..1335a4933 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -45,14 +45,12 @@ private inline class Buffer1DWrapper(val buffer: Buffer) : Structure1D /** * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch */ -public fun NDStructure.as1D(): Structure1D = if (shape.size == 1) { +public fun NDStructure.as1D(): Structure1D = this as? Structure1D ?: if (shape.size == 1) { when (this) { - is Structure1DWrapper -> this is NDBuffer -> Buffer1DWrapper(this.buffer) else -> Structure1DWrapper(this) } -} else - error("Can't create 1d-structure from ${shape.size}d-structure") +} else error("Can't create 1d-structure from ${shape.size}d-structure") /** * Represent this buffer as 1D structure diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 09c830646..e9f8234e5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -26,14 +26,14 @@ public interface Structure2D : NDStructure { /** * The buffer of rows of this structure. It gets elements from the structure dynamically. */ - public val rows: Buffer> - get() = VirtualBuffer(rowNum) { i -> VirtualBuffer(colNum) { j -> get(i, j) } } + public val rows: List> + get() = List(rowNum) { i -> VirtualBuffer(colNum) { j -> get(i, j) } } /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ - public val columns: Buffer> - get() = VirtualBuffer(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } } + public val columns: List> + get() = List(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } } /** * Retrieves an element from the structure by two indices. @@ -75,20 +75,15 @@ private class Structure2DWrapper(val structure: NDStructure) : Structure2D override fun equals(other: Any?): Boolean = structure == other - override fun hashCode(): Int = structure.hashCode() + override fun hashCode(): Int = structure.hashCode() } /** * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch */ -public fun NDStructure.as2D(): Structure2D = if (shape.size == 2) - Structure2DWrapper(this) -else - error("Can't create 2d-structure from ${shape.size}d-structure") +public fun NDStructure.as2D(): Structure2D = this as? Structure2D ?: when (shape.size) { + 2 -> Structure2DWrapper(this) + else -> error("Can't create 2d-structure from ${shape.size}d-structure") +} -/** - * Alias for [Structure2D] with more familiar name. - * - * @param T the type of items in the matrix. - */ -public typealias Matrix = Structure2D +internal fun Structure2D.unwrap(): NDStructure = if (this is Structure2DWrapper) structure else this \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt index d9e37ebd8..0910b2034 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt @@ -13,10 +13,10 @@ internal class BufferAccessor2D( public val colNum: Int, val factory: MutableBufferFactory, ) { - public operator fun Buffer.get(i: Int, j: Int): T = get(i + colNum * j) + public operator fun Buffer.get(i: Int, j: Int): T = get(i*colNum + j) public operator fun MutableBuffer.set(i: Int, j: Int, value: T) { - set(i + colNum * j, value) + set(i*colNum + j, value) } public inline fun create(crossinline init: (i: Int, j: Int) -> T): MutableBuffer = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt new file mode 100644 index 000000000..459136631 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt @@ -0,0 +1,7 @@ +package space.kscience.kmath.structures + + +public inline fun Buffer.map( + bufferFactory: BufferFactory = Buffer.Companion::auto, + crossinline block: (T) -> R, +): Buffer = bufferFactory(size) { block(get(it)) } \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt index 704f91998..fb90b5e11 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt @@ -19,13 +19,13 @@ class RealLUSolverTest { LinearSpace.real.run { val matrix = matrix(2,2)( 3.0, 1.0, - 1.0, 3.0 + 2.0, 3.0 ) val lup = lup(matrix) //Check determinant - assertEquals(8.0, lup.determinant) + assertEquals(7.0, lup.determinant) assertEquals(lup.p dot matrix, lup.l dot lup.u) } diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index 57ce977fd..2d3a928a6 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -5,14 +5,13 @@ import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.getFeature import space.kscience.kmath.operations.RealField -import space.kscience.kmath.operations.ScaleOperations /** * Represents context of basic operations operating with [EjmlMatrix]. * * @author Iaroslav Postovalov */ -public object EjmlLinearSpace : LinearSpace, ScaleOperations> { +public object EjmlLinearSpace : LinearSpace { override val elementAlgebra: RealField get() = RealField @@ -50,7 +49,7 @@ public object EjmlLinearSpace : LinearSpace, ScaleOperations< private fun SimpleMatrix.wrapMatrix() = EjmlMatrix(this) private fun SimpleMatrix.wrapVector() = EjmlVector(this) - override fun Matrix.unaryMinus(): Matrix = this * (-1) + override fun Matrix.unaryMinus(): Matrix = this * (-1.0) public override fun Matrix.dot(other: Matrix): EjmlMatrix = EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) @@ -61,9 +60,6 @@ public object EjmlLinearSpace : LinearSpace, ScaleOperations< public override operator fun Matrix.minus(other: Matrix): EjmlMatrix = (toEjml().origin - other.toEjml().origin).wrapMatrix() - public override fun scale(a: Matrix, value: Double): EjmlMatrix = - a.toEjml().origin.scale(value).wrapMatrix() - public override operator fun Matrix.times(value: Double): EjmlMatrix = toEjml().origin.scale(value).wrapMatrix() diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt index 1a7c1213c..0bc5c111b 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.real import space.kscience.kmath.linear.LinearSpace -import space.kscience.kmath.nd.Matrix +import space.kscience.kmath.linear.Matrix /** From 8179be2f6284a01fa5ebfb020ee2051c83265655 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 14 Mar 2021 09:55:24 +0300 Subject: [PATCH 070/393] cleanup --- .../linear/{LinearSpaceOverNd.kt => BufferLinearSpace.kt} | 6 ++---- .../kotlin/space/kscience/kmath/linear/LinearSpace.kt | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/{LinearSpaceOverNd.kt => BufferLinearSpace.kt} (94%) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpaceOverNd.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt similarity index 94% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpaceOverNd.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt index 6a82f37ec..1ea138063 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpaceOverNd.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.structures.VirtualBuffer import space.kscience.kmath.structures.indices -public class LinearSpaceOverNd>( +public class BufferLinearSpace>( override val elementAlgebra: A, private val bufferFactory: BufferFactory, ) : LinearSpace { @@ -35,7 +35,7 @@ public class LinearSpaceOverNd>( } override fun Matrix.minus(other: Matrix): Matrix = ndRing(rowNum, colNum).run { - require(shape.contentEquals(other.shape)) { "Shape mismatch on Matrix::plus. Expected $shape but found ${other.shape}" } + require(shape.contentEquals(other.shape)) { "Shape mismatch on Matrix::minus. Expected $shape but found ${other.shape}" } unwrap().minus(other.unwrap()).as2D() } @@ -50,7 +50,6 @@ public class LinearSpaceOverNd>( return elementAlgebra { val rows = this@dot.rows.map{it.linearize()} val columns = other.columns.map { it.linearize() } - //TODO optimize buffers buildMatrix(rowNum, other.colNum) { i, j -> val r = rows[i] val c = columns[j] @@ -67,7 +66,6 @@ public class LinearSpaceOverNd>( require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } return elementAlgebra { val rows = this@dot.rows - //TODO optimize buffers buildVector(rowNum) { i -> val r = rows[i] var res = zero diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index b0331bdea..4fd4d28d1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -171,7 +171,7 @@ public interface LinearSpace> { public fun > buffered( algebra: A, bufferFactory: BufferFactory = Buffer.Companion::boxing, - ): LinearSpace = LinearSpaceOverNd(algebra,bufferFactory) + ): LinearSpace = BufferLinearSpace(algebra,bufferFactory) public val real: LinearSpace = buffered(RealField, Buffer.Companion::real) From 0cc68e72ce58eaca0efe362309ccf0fa72724cf0 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 14 Mar 2021 09:59:53 +0300 Subject: [PATCH 071/393] cleanup --- .../kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt index 1ea138063..ac6211c4b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt @@ -65,7 +65,7 @@ public class BufferLinearSpace>( override fun Matrix.dot(vector: Vector): Vector { require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } return elementAlgebra { - val rows = this@dot.rows + val rows = this@dot.rows.map { it.linearize() } buildVector(rowNum) { i -> val r = rows[i] var res = zero From 5a568c4587ba1b93a1c83d0b5eb2cecd7fe40dbf Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 14 Mar 2021 14:23:53 +0300 Subject: [PATCH 072/393] add gradient example --- .../space/kscience/kmath/linear/gradient.kt | 28 ++++++++++++++ kmath-core/api/kmath-core.api | 38 +++++++++---------- .../space/kscience/kmath/real/RealVector.kt | 19 ++++++++-- 3 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt new file mode 100644 index 000000000..ce2b9cb00 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt @@ -0,0 +1,28 @@ +package space.kscience.kmath.linear + +import space.kscience.kmath.real.* +import space.kscience.kmath.structures.RealBuffer + +fun main() { + val x0 = Vector(0.0, 0.0, 0.0) + val sigma = Vector(1.0, 1.0, 1.0) + + val gaussian: (Vector) -> Double = { x -> + require(x.size == x0.size) + kotlin.math.exp(-((x - x0) / sigma).square().sum()) + } + + fun ((Vector) -> Double).grad(x: Vector): Vector { + require(x.size == x0.size) + return RealBuffer(x.size) { i -> + val h = sigma[i] / 5 + val dVector = RealBuffer(x.size) { if (it == i) h else 0.0 } + val f1 = invoke(x + dVector / 2) + val f0 = invoke(x - dVector / 2) + (f1 - f0) / h + } + } + + println(gaussian.grad(x0)) + +} \ No newline at end of file diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 38da35d6c..525711e96 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -432,6 +432,25 @@ public final class space/kscience/kmath/expressions/SymbolIndexerKt { public static final fun withSymbols ([Lspace/kscience/kmath/expressions/Symbol;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } +public final class space/kscience/kmath/linear/BufferLinearSpace : space/kscience/kmath/linear/LinearSpace { + public fun (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V + public fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D; + public fun buildVector (ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; + public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun getElementAlgebra ()Lspace/kscience/kmath/operations/Ring; + public fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun times (Ljava/lang/Object;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; + public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; + public fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; +} + public abstract interface class space/kscience/kmath/linear/CholeskyDecompositionFeature : space/kscience/kmath/linear/MatrixFeature { public abstract fun getL ()Lspace/kscience/kmath/nd/Structure2D; } @@ -514,25 +533,6 @@ public final class space/kscience/kmath/linear/LinearSpaceKt { public static final fun invoke (Lspace/kscience/kmath/linear/LinearSpace;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } -public final class space/kscience/kmath/linear/LinearSpaceOverNd : space/kscience/kmath/linear/LinearSpace { - public fun (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V - public fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D; - public fun buildVector (ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; - public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun getElementAlgebra ()Lspace/kscience/kmath/operations/Ring; - public fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun times (Ljava/lang/Object;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; - public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; - public fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; -} - public final class space/kscience/kmath/linear/LupDecomposition : space/kscience/kmath/linear/DeterminantFeature, space/kscience/kmath/linear/LupDecompositionFeature { public fun (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/operations/Field;Lspace/kscience/kmath/nd/Structure2D;[IZ)V public final fun getContext ()Lspace/kscience/kmath/linear/LinearSpace; diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt index ca892fa7e..ee42fe404 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt @@ -5,6 +5,7 @@ import space.kscience.kmath.operations.Norm import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.asIterable +import space.kscience.kmath.structures.indices import kotlin.math.pow import kotlin.math.sqrt @@ -30,7 +31,7 @@ public inline fun RealVector.mapIndexed(transform: (index: Int, value: Double) - Buffer.real(size) { transform(it, get(it)) } public operator fun RealVector.plus(other: RealVector): RealVector { - require(size == other.size){"Vector size $size expected but ${other.size} found"} + require(size == other.size) { "Vector size $size expected but ${other.size} found" } return mapIndexed { index, value -> value + other[index] } } @@ -41,7 +42,7 @@ public operator fun Number.plus(vector: RealVector): RealVector = vector + this public operator fun RealVector.unaryMinus(): Buffer = map { -it } public operator fun RealVector.minus(other: RealVector): RealVector { - require(size == other.size){"Vector size $size expected but ${other.size} found"} + require(size == other.size) { "Vector size $size expected but ${other.size} found" } return mapIndexed { index, value -> value - other[index] } } @@ -50,7 +51,7 @@ public operator fun RealVector.minus(number: Number): RealVector = map { it - nu public operator fun Number.minus(vector: RealVector): RealVector = vector.map { toDouble() - it } public operator fun RealVector.times(other: RealVector): RealVector { - require(size == other.size){"Vector size $size expected but ${other.size} found"} + require(size == other.size) { "Vector size $size expected but ${other.size} found" } return mapIndexed { index, value -> value * other[index] } } @@ -59,7 +60,7 @@ public operator fun RealVector.times(number: Number): RealVector = map { it * nu public operator fun Number.times(vector: RealVector): RealVector = vector * this public operator fun RealVector.div(other: RealVector): RealVector { - require(size == other.size){"Vector size $size expected but ${other.size} found"} + require(size == other.size) { "Vector size $size expected but ${other.size} found" } return mapIndexed { index, value -> value / other[index] } } @@ -88,3 +89,13 @@ public fun tan(vector: RealVector): RealVector = vector.map { kotlin.math.tan(it public fun ln(vector: RealVector): RealVector = vector.map { kotlin.math.ln(it) } public fun log10(vector: RealVector): RealVector = vector.map { kotlin.math.log10(it) } + +// reductions methods + +public fun RealVector.sum(): Double { + var res = 0.0 + for (i in indices) { + res += get(i) + } + return res +} \ No newline at end of file From e01f90b5e03d42a7c0c50591f34222c3607edff5 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 14 Mar 2021 14:40:13 +0300 Subject: [PATCH 073/393] add gradient example --- CHANGELOG.md | 1 + .../space/kscience/kmath/linear/gradient.kt | 8 +- .../kscience/kmath/commons/linear/CMMatrix.kt | 16 ++-- kmath-core/api/kmath-core.api | 10 +-- .../kmath/linear/BufferLinearSpace.kt | 4 +- .../{LinearAlgebra.kt => LinearSolver.kt} | 5 +- .../kscience/kmath/linear/LinearSpace.kt | 19 ++-- .../kscience/kmath/linear/MatrixBuilder.kt | 2 +- .../kscience/kmath/linear/RealLinearSpace.kt | 86 ------------------- .../kscience/kmath/ejml/EjmlLinearSpace.kt | 16 ++-- 10 files changed, 41 insertions(+), 126 deletions(-) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/{LinearAlgebra.kt => LinearSolver.kt} (83%) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealLinearSpace.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 05c956de3..47690e36a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Exponential operations merged with hyperbolic functions - Space is replaced by Group. Space is reserved for vector spaces. - VectorSpace is now a vector space +- ### Deprecated diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt index ce2b9cb00..8dd3d7f6b 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt @@ -4,15 +4,15 @@ import space.kscience.kmath.real.* import space.kscience.kmath.structures.RealBuffer fun main() { - val x0 = Vector(0.0, 0.0, 0.0) - val sigma = Vector(1.0, 1.0, 1.0) + val x0 = Point(0.0, 0.0, 0.0) + val sigma = Point(1.0, 1.0, 1.0) - val gaussian: (Vector) -> Double = { x -> + val gaussian: (Point) -> Double = { x -> require(x.size == x0.size) kotlin.math.exp(-((x - x0) / sigma).square().sum()) } - fun ((Vector) -> Double).grad(x: Vector): Vector { + fun ((Point) -> Double).grad(x: Point): Point { require(x.size == x0.size) return RealBuffer(x.size) { i -> val h = sigma[i] / 5 diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index b462a1a36..5f632491c 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -62,7 +62,7 @@ public class CMMatrix(public val origin: RealMatrix) : Matrix { override fun hashCode(): Int = origin.hashCode() } -public inline class CMVector(public val origin: RealVector) : Vector { +public inline class CMVector(public val origin: RealVector) : Point { public override val size: Int get() = origin.dimension public override operator fun get(index: Int): Double = origin.getEntry(index) @@ -94,7 +94,7 @@ public object CMLinearSpace : LinearSpace { } } - public fun Vector.toCM(): CMVector = if (this is CMVector) this else { + public fun Point.toCM(): CMVector = if (this is CMVector) this else { val array = DoubleArray(size) { this[it] } ArrayRealVector(array).wrap() } @@ -102,22 +102,22 @@ public object CMLinearSpace : LinearSpace { internal fun RealMatrix.wrap(): CMMatrix = CMMatrix(this) internal fun RealVector.wrap(): CMVector = CMVector(this) - override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Vector = + override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Point = ArrayRealVector(DoubleArray(size) { RealField.initializer(it) }).wrap() override fun Matrix.plus(other: Matrix): CMMatrix = toCM().origin.add(other.toCM().origin).wrap() - override fun Vector.plus(other: Vector): CMVector = + override fun Point.plus(other: Point): CMVector = toCM().origin.add(other.toCM().origin).wrap() - override fun Vector.minus(other: Vector): CMVector = + override fun Point.minus(other: Point): CMVector = toCM().origin.subtract(other.toCM().origin).wrap() public override fun Matrix.dot(other: Matrix): CMMatrix = toCM().origin.multiply(other.toCM().origin).wrap() - public override fun Matrix.dot(vector: Vector): CMVector = + public override fun Matrix.dot(vector: Point): CMVector = toCM().origin.preMultiply(vector.toCM().origin).wrap() public override operator fun Matrix.minus(other: Matrix): CMMatrix = @@ -129,10 +129,10 @@ public object CMLinearSpace : LinearSpace { override fun Double.times(m: Matrix): CMMatrix = m * this - override fun Vector.times(value: Double): CMVector = + override fun Point.times(value: Double): CMVector = toCM().origin.mapMultiply(value).wrap() - override fun Double.times(v: Vector): CMVector = + override fun Double.times(v: Point): CMVector = v * this } diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 525711e96..b2417fa7d 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -474,11 +474,6 @@ public final class space/kscience/kmath/linear/LFeature : space/kscience/kmath/l public static final field INSTANCE Lspace/kscience/kmath/linear/LFeature; } -public final class space/kscience/kmath/linear/LinearAlgebraKt { - public static final fun asMatrix (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/linear/VirtualMatrix; - public static final fun asVector (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/structures/Buffer; -} - public abstract interface class space/kscience/kmath/linear/LinearSolver { public abstract fun inverse (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public abstract fun solve (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; @@ -489,6 +484,11 @@ public final class space/kscience/kmath/linear/LinearSolver$DefaultImpls { public static fun solve (Lspace/kscience/kmath/linear/LinearSolver;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; } +public final class space/kscience/kmath/linear/LinearSolverKt { + public static final fun asMatrix (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/linear/VirtualMatrix; + public static final fun asVector (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/structures/Buffer; +} + public abstract interface class space/kscience/kmath/linear/LinearSpace { public static final field Companion Lspace/kscience/kmath/linear/LinearSpace$Companion; public abstract fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt index ac6211c4b..b6c2ea17b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt @@ -22,7 +22,7 @@ public class BufferLinearSpace>( override fun buildMatrix(rows: Int, columns: Int, initializer: A.(i: Int, j: Int) -> T): Matrix = ndRing(rows, columns).produce { (i, j) -> elementAlgebra.initializer(i, j) }.as2D() - override fun buildVector(size: Int, initializer: A.(Int) -> T): Vector = + override fun buildVector(size: Int, initializer: A.(Int) -> T): Point = bufferFactory(size) { elementAlgebra.initializer(it) } override fun Matrix.unaryMinus(): Matrix = ndRing(rowNum, colNum).run { @@ -62,7 +62,7 @@ public class BufferLinearSpace>( } } - override fun Matrix.dot(vector: Vector): Vector { + override fun Matrix.dot(vector: Point): Point { require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } return elementAlgebra { val rows = this@dot.rows.map { it.linearize() } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt similarity index 83% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt index 265a709e9..6cce5a446 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt @@ -1,9 +1,6 @@ package space.kscience.kmath.linear import space.kscience.kmath.nd.as1D -import space.kscience.kmath.structures.Buffer - -public typealias Point = Buffer /** * A group of methods to resolve equation A dot X = B, where A and B are matrices or vectors @@ -17,7 +14,7 @@ public interface LinearSolver { /** * Convert matrix to vector if it is possible */ -public fun Matrix.asVector(): Vector = +public fun Matrix.asVector(): Point = if (this.colNum == 1) as1D() else diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 4fd4d28d1..de9ac35db 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -14,7 +14,10 @@ import kotlin.reflect.KClass */ public typealias Matrix = Structure2D -public typealias Vector = Point +/** + * Alias or using [Buffer] as a point/vector in a many-dimensional space. + */ +public typealias Point = Buffer /** * Basic operations on matrices and vectors. Operates on [Matrix]. @@ -33,13 +36,13 @@ public interface LinearSpace> { /** * Produces a point compatible with matrix space (and possibly optimized for it). */ - public fun buildVector(size: Int, initializer: A.(Int) -> T): Vector + public fun buildVector(size: Int, initializer: A.(Int) -> T): Point public operator fun Matrix.unaryMinus(): Matrix = buildMatrix(rowNum, colNum) { i, j -> -get(i, j) } - public operator fun Vector.unaryMinus(): Vector = buildVector(size) { + public operator fun Point.unaryMinus(): Point = buildVector(size) { -get(it) } @@ -54,7 +57,7 @@ public interface LinearSpace> { /** * Vector sum */ - public operator fun Vector.plus(other: Vector): Vector = buildVector(size) { + public operator fun Point.plus(other: Point): Point = buildVector(size) { get(it) + other[it] } @@ -68,7 +71,7 @@ public interface LinearSpace> { /** * Vector subtraction */ - public operator fun Vector.minus(other: Vector): Vector = buildVector(size) { + public operator fun Point.minus(other: Point): Point = buildVector(size) { get(it) - other[it] } @@ -100,7 +103,7 @@ public interface LinearSpace> { * @param vector the multiplier. * @return the dot product. */ - public infix fun Matrix.dot(vector: Vector): Vector { + public infix fun Matrix.dot(vector: Point): Point { require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } return elementAlgebra { buildVector(rowNum) { i -> @@ -139,7 +142,7 @@ public interface LinearSpace> { * @param value the multiplier. * @receiver the product. */ - public operator fun Vector.times(value: T): Vector = + public operator fun Point.times(value: T): Point = buildVector(size) { i -> get(i) * value } /** @@ -149,7 +152,7 @@ public interface LinearSpace> { * @param v the multiplier. * @receiver the product. */ - public operator fun T.times(v: Vector): Vector = v * this + public operator fun T.times(v: Point): Point = v * this /** * Gets a feature from the matrix. This function may return some additional features to diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt index 0a7f280bc..b30d621fe 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt @@ -24,7 +24,7 @@ public fun > LinearSpace.matrix(rows: Int, columns: I MatrixBuilder(this, rows, columns) @UnstableKMathAPI -public fun LinearSpace>.vector(vararg elements: T): Vector { +public fun LinearSpace>.vector(vararg elements: T): Point { return buildVector(elements.size) { elements[it] } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealLinearSpace.kt deleted file mode 100644 index 3fa23db82..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/RealLinearSpace.kt +++ /dev/null @@ -1,86 +0,0 @@ -package space.kscience.kmath.linear - -//public object RealLinearSpace: - -//public object RealLinearSpace : LinearSpace, ScaleOperations> { -// -// override val elementAlgebra: RealField get() = RealField -// -// public override fun buildMatrix( -// rows: Int, -// columns: Int, -// initializer: (i: Int, j: Int) -> Double, -// ): Matrix { -// val buffer = RealBuffer(rows * columns) { offset -> initializer(offset / columns, offset % columns) } -// return BufferMatrix(rows, columns, buffer) -// } -// -// public fun Matrix.toBufferMatrix(): BufferMatrix = if (this is BufferMatrix) this else { -// buildMatrix(rowNum, colNum) { i, j -> get(i, j) } -// } -// -// public fun one(rows: Int, columns: Int): Matrix = VirtualMatrix(rows, columns) { i, j -> -// if (i == j) 1.0 else 0.0 -// } + DiagonalFeature -// -// override fun Matrix.unaryMinus(): Matrix = buildMatrix(rowNum, colNum) { i, j -> -get(i, j) } -// -// public override infix fun Matrix.dot(other: Matrix): BufferMatrix { -// require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } -// val bufferMatrix = toBufferMatrix() -// val otherBufferMatrix = other.toBufferMatrix() -// return buildMatrix(rowNum, other.colNum) { i, j -> -// var res = 0.0 -// for (l in 0 until colNum) { -// res += bufferMatrix[i, l] * otherBufferMatrix[l, j] -// } -// res -// } -// } -// -// public override infix fun Matrix.dot(vector: Point): Point { -// require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } -// val bufferMatrix = toBufferMatrix() -// return RealBuffer(rowNum) { i -> -// var res = 0.0 -// for (j in 0 until colNum) { -// res += bufferMatrix[i, j] * vector[j] -// } -// res -// } -// } -// -// override fun add(a: Matrix, b: Matrix): BufferMatrix { -// require(a.rowNum == b.rowNum) { "Row number mismatch in matrix addition. Left side: ${a.rowNum}, right side: ${b.rowNum}" } -// require(a.colNum == b.colNum) { "Column number mismatch in matrix addition. Left side: ${a.colNum}, right side: ${b.colNum}" } -// val aBufferMatrix = a.toBufferMatrix() -// val bBufferMatrix = b.toBufferMatrix() -// return buildMatrix(a.rowNum, a.colNum) { i, j -> -// aBufferMatrix[i, j] + bBufferMatrix[i, j] -// } -// } -// -// override fun scale(a: Matrix, value: Double): BufferMatrix { -// val bufferMatrix = a.toBufferMatrix() -// return buildMatrix(a.rowNum, a.colNum) { i, j -> bufferMatrix[i, j] * value } -// } -// -// override fun Matrix.times(value: Double): BufferMatrix = scale(this, value) -// -//// -//// override fun multiply(a: Matrix, k: Number): BufferMatrix { -//// val aBufferMatrix = a.toBufferMatrix() -//// return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() } -//// } -//// -//// override fun divide(a: Matrix, k: Number): BufferMatrix { -//// val aBufferMatrix = a.toBufferMatrix() -//// return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] / k.toDouble() } -//// } -//} - - -///** -// * Partially optimized real-valued matrix -// */ -//public val LinearSpace.Companion.real: RealLinearSpace get() = RealLinearSpace diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index 2d3a928a6..eecd88681 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -27,7 +27,7 @@ public object EjmlLinearSpace : LinearSpace { /** * Converts this vector to EJML one. */ - public fun Vector.toEjml(): EjmlVector = when (this) { + public fun Point.toEjml(): EjmlVector = when (this) { is EjmlVector -> this else -> EjmlVector(SimpleMatrix(size, 1).also { (0 until it.numRows()).forEach { row -> it[row, 0] = get(row) } @@ -41,7 +41,7 @@ public object EjmlLinearSpace : LinearSpace { } }) - override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Vector = + override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Point = EjmlVector(SimpleMatrix(size, 1).also { (0 until it.numRows()).forEach { row -> it[row, 0] = RealField.initializer(row) } }) @@ -54,7 +54,7 @@ public object EjmlLinearSpace : LinearSpace { public override fun Matrix.dot(other: Matrix): EjmlMatrix = EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) - public override fun Matrix.dot(vector: Vector): EjmlVector = + public override fun Matrix.dot(vector: Point): EjmlVector = EjmlVector(toEjml().origin.mult(vector.toEjml().origin)) public override operator fun Matrix.minus(other: Matrix): EjmlMatrix = @@ -63,25 +63,25 @@ public object EjmlLinearSpace : LinearSpace { public override operator fun Matrix.times(value: Double): EjmlMatrix = toEjml().origin.scale(value).wrapMatrix() - override fun Vector.unaryMinus(): EjmlVector = + override fun Point.unaryMinus(): EjmlVector = toEjml().origin.negative().wrapVector() override fun Matrix.plus(other: Matrix): EjmlMatrix = (toEjml().origin + other.toEjml().origin).wrapMatrix() - override fun Vector.plus(other: Vector): EjmlVector = + override fun Point.plus(other: Point): EjmlVector = (toEjml().origin + other.toEjml().origin).wrapVector() - override fun Vector.minus(other: Vector): EjmlVector = + override fun Point.minus(other: Point): EjmlVector = (toEjml().origin - other.toEjml().origin).wrapVector() override fun Double.times(m: Matrix): EjmlMatrix = m.toEjml().origin.scale(this).wrapMatrix() - override fun Vector.times(value: Double): EjmlVector = + override fun Point.times(value: Double): EjmlVector = toEjml().origin.scale(value).wrapVector() - override fun Double.times(v: Vector): EjmlVector = + override fun Double.times(v: Point): EjmlVector = v.toEjml().origin.scale(this).wrapVector() } From 6c451b5ca7d5891e1553d5023dd4e42c662db234 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 14 Mar 2021 15:09:04 +0300 Subject: [PATCH 074/393] fix doc typo --- .../kotlin/space/kscience/kmath/linear/LinearSpace.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index de9ac35db..1642bfb14 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -156,7 +156,7 @@ public interface LinearSpace> { /** * Gets a feature from the matrix. This function may return some additional features to - * [group.kscience.kmath.nd.NDStructure.getFeature]. + * [space.kscience.kmath.nd.NDStructure.getFeature]. * * @param F the type of feature. * @param m the matrix. @@ -190,7 +190,7 @@ public operator fun , R> LS.invoke(block: LS.() -> R): R /** * Gets a feature from the matrix. This function may return some additional features to - * [group.kscience.kmath.nd.NDStructure.getFeature]. + * [space.kscience.kmath.nd.NDStructure.getFeature]. * * @param T the type of items in the matrices. * @param M the type of operated matrices. From c02f71263ded2c41806c821c351c58fd40d868ec Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sun, 14 Mar 2021 21:18:20 +0000 Subject: [PATCH 075/393] Adding the interfaces for AnalyticTensorAlgebra and LinearOpsTensorAlgebra --- .../kmath/tensors/AnalyticTensorAlgebra.kt | 112 +++++++++++ .../kmath/tensors/LinearOpsTensorAlgebra.kt | 43 ++++ .../tensors/RealAnalyticTensorAlgebra.kt | 148 ++++++++++++++ .../tensors/RealLinearOpsTensorAlgebra.kt | 133 +++++++++++++ .../kmath/tensors/RealTensorAlgebra.kt | 185 +++++++----------- .../kscience/kmath/tensors/TensorAlgebra.kt | 93 +++++---- .../tensors/TensorPartialDivisionAlgebra.kt | 27 +++ 7 files changed, 586 insertions(+), 155 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt new file mode 100644 index 000000000..17a25b6b3 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt @@ -0,0 +1,112 @@ +package space.kscience.kmath.tensors + + +public interface AnalyticTensorAlgebra> : + TensorPartialDivisionAlgebra { + + //https://pytorch.org/docs/stable/generated/torch.exp.html + public fun TensorType.exp(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.log.html + public fun TensorType.log(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.sqrt.html + public fun TensorType.sqrt(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.square.html + public fun TensorType.square(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos + public fun TensorType.cos(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.acos + public fun TensorType.acos(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.cosh + public fun TensorType.cosh(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.acosh + public fun TensorType.acosh(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sin + public fun TensorType.sin(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asin + public fun TensorType.asin(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sinh + public fun TensorType.sinh(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asinh + public fun TensorType.asinh(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.tan + public fun TensorType.tan(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.atan + public fun TensorType.atan(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.tanh + public fun TensorType.tanh(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.atanh + public fun TensorType.atanh(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.ceil.html#torch.ceil + public fun TensorType.ceil(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor + public fun TensorType.floor(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.clamp.html#torch.clamp + public fun TensorType.clamp(min: T, max: T): TensorType + + //https://pytorch.org/docs/stable/generated/torch.erf.html#torch.erf + public fun TensorType.erf(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.erfinv.html#torch.erfinv + public fun TensorType.erfinv(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.erfc.html#torch.erfc + public fun TensorType.erfc(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.lerp.html#torch.lerp + public fun TensorType.lerp(end: TensorType, weight: TensorType): TensorType + + //https://pytorch.org/docs/stable/generated/torch.lgamma.html#torch.lgamma + public fun TensorType.lgamma(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.logit.html#torch.logit + public fun TensorType.logit(eps: T): TensorType + + //https://pytorch.org/docs/stable/generated/torch.igamma.html#torch.igamma + public fun TensorType.igamma(other: TensorType): TensorType + + //https://pytorch.org/docs/stable/generated/torch.igammac.html#torch.igammac + public fun TensorType.igammac(other: TensorType): TensorType + + //https://pytorch.org/docs/stable/generated/torch.mvlgamma.html#torch.mvlgamma + public fun TensorType.mvlgamma(dimensions: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.polygamma.html#torch.polygamma + public fun TensorType.polygamma(order: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.pow.html#torch.pow + public fun TensorType.pow(exponent: T): TensorType + + //https://pytorch.org/docs/stable/generated/torch.round.html#torch.round + public fun TensorType.round(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.sigmoid.html#torch.sigmoid + public fun TensorType.sigmoid(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.sinc.html#torch.sinc + public fun TensorType.sinc(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.heaviside.html#torch.heaviside + public fun TensorType.heaviside(values: TensorType): TensorType + + //https://pytorch.org/docs/stable/generated/torch.trapz.html#torch.trapz + public fun TensorType.trapz(xValues: TensorType, dim: Int): TensorType + +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt new file mode 100644 index 000000000..bd9cbfd45 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -0,0 +1,43 @@ +package space.kscience.kmath.tensors + + +public interface LinearOpsTensorAlgebra> : + TensorPartialDivisionAlgebra { + + //https://pytorch.org/docs/stable/generated/torch.eye.html + public fun eye(n: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.matmul.html + public infix fun TensorType.dot(other: TensorType): TensorType + + //https://pytorch.org/docs/stable/generated/torch.diag_embed.html + public fun diagonalEmbedding( + diagonalEntries: TensorType, + offset: Int = 0, dim1: Int = -2, dim2: Int = -1 + ): TensorType + + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det + public fun TensorType.det(): TensorType + + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv + public fun TensorType.inv(): TensorType + + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.cholesky + public fun TensorType.cholesky(): TensorType + + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr + public fun TensorType.qr(): TensorType + + //https://pytorch.org/docs/stable/generated/torch.lu.html + public fun TensorType.lu(): Pair + + //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html + public fun luPivot(aLU: TensorType, pivots: IntTensor): Triple + + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd + public fun TensorType.svd(): Triple + + //https://pytorch.org/docs/stable/generated/torch.symeig.html + public fun TensorType.symEig(eigenvectors: Boolean = true): Pair + +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt new file mode 100644 index 000000000..cfecac0f4 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt @@ -0,0 +1,148 @@ +package space.kscience.kmath.tensors + +public class RealAnalyticTensorAlgebra: + AnalyticTensorAlgebra, + RealTensorAlgebra() +{ + override fun RealTensor.exp(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.log(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.sqrt(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.square(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.cos(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.acos(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.cosh(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.acosh(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.sin(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.asin(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.sinh(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.asinh(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.tan(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.atan(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.tanh(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.atanh(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.ceil(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.floor(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.clamp(min: Double, max: Double): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.erf(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.erfinv(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.erfc(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.lerp(end: RealTensor, weight: RealTensor): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.lgamma(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.logit(eps: Double): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.igamma(other: RealTensor): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.igammac(other: RealTensor): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.mvlgamma(dimensions: Int): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.polygamma(order: Int): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.pow(exponent: Double): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.round(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.sigmoid(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.sinc(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.heaviside(values: RealTensor): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.trapz(xValues: RealTensor, dim: Int): RealTensor { + TODO("Not yet implemented") + } + + +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt new file mode 100644 index 000000000..18c2050c0 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt @@ -0,0 +1,133 @@ +package space.kscience.kmath.tensors + +import space.kscience.kmath.structures.array + +public class RealLinearOpsTensorAlgebra : + LinearOpsTensorAlgebra, + RealTensorAlgebra() +{ + override fun eye(n: Int): RealTensor { + val shape = intArrayOf(n, n) + val buffer = DoubleArray(n * n) { 0.0 } + val res = RealTensor(shape, buffer) + for (i in 0 until n) { + res[intArrayOf(i, i)] = 1.0 + } + return res + } + + + override fun RealTensor.dot(other: RealTensor): RealTensor { + TODO("Alya") + } + + override fun diagonalEmbedding(diagonalEntries: RealTensor, offset: Int, dim1: Int, dim2: Int): RealTensor { + TODO("Alya") + } + + + override fun RealTensor.lu(): Pair { + // todo checks + val lu = this.copy() + val m = this.shape[0] + val pivot = IntArray(m) + + + // Initialize permutation array and parity + for (row in 0 until m) pivot[row] = row + var even = true + + for (i in 0 until m) { + var maxA = -1.0 + var iMax = i + + for (k in i until m) { + val absA = kotlin.math.abs(lu[k, i]) + if (absA > maxA) { + maxA = absA + iMax = k + } + } + + //todo check singularity + + if (iMax != i) { + + val j = pivot[i] + pivot[i] = pivot[iMax] + pivot[iMax] = j + even != even + + for (k in 0 until m) { + val tmp = lu[i, k] + lu[i, k] = lu[iMax, k] + lu[iMax, k] = tmp + } + + } + + for (j in i + 1 until m) { + lu[j, i] /= lu[i, i] + for (k in i + 1 until m) { + lu[j, k] -= lu[j, i] * lu[i, k] + } + } + } + return Pair(lu, IntTensor(intArrayOf(m), pivot)) + } + + override fun luPivot(lu: RealTensor, pivots: IntTensor): Triple { + // todo checks + val n = lu.shape[0] + val p = lu.zeroesLike() + pivots.buffer.array.forEachIndexed { i, pivot -> + p[i, pivot] = 1.0 + } + val l = lu.zeroesLike() + val u = lu.zeroesLike() + + for (i in 0 until n) { + for (j in 0 until n) { + if (i == j) { + l[i, j] = 1.0 + } + if (j < i) { + l[i, j] = lu[i, j] + } + if (j >= i) { + u[i, j] = lu[i, j] + } + } + } + return Triple(p, l, u) + } + + override fun RealTensor.det(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.inv(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.cholesky(): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.qr(): RealTensor { + TODO("Not yet implemented") + } + + + override fun RealTensor.svd(): Triple { + TODO("Not yet implemented") + } + + override fun RealTensor.symEig(eigenvectors: Boolean): Pair { + TODO("Not yet implemented") + } + +} + +public inline fun RealLinearOpsTensorAlgebra(block: RealTensorAlgebra.() -> R): R = + RealTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index b3e54f077..05e2b57d2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,12 +1,9 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.RealBuffer import space.kscience.kmath.structures.array -import kotlin.math.abs -import kotlin.math.max -public class RealTensorAlgebra : TensorPartialDivisionAlgebra { +public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { override fun RealTensor.value(): Double { check(this.shape contentEquals intArrayOf(1)) { @@ -15,24 +12,13 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra, dim: Int): RealTensor { TODO("Not yet implemented") } @@ -213,6 +246,10 @@ public class RealTensorAlgebra : TensorPartialDivisionAlgebra { - // todo checks - val lu = this.copy() - val m = this.shape[0] - val pivot = IntArray(m) - - - // Initialize permutation array and parity - for (row in 0 until m) pivot[row] = row - var even = true - - for (i in 0 until m) { - var maxA = -1.0 - var iMax = i - - for (k in i until m) { - val absA = abs(lu[k, i]) - if (absA > maxA) { - maxA = absA - iMax = k - } - } - - //todo check singularity - - if (iMax != i) { - - val j = pivot[i] - pivot[i] = pivot[iMax] - pivot[iMax] = j - even != even - - for (k in 0 until m) { - val tmp = lu[i, k] - lu[i, k] = lu[iMax, k] - lu[iMax, k] = tmp - } - - } - - for (j in i + 1 until m) { - lu[j, i] /= lu[i, i] - for (k in i + 1 until m) { - lu[j, k] -= lu[j, i] * lu[i, k] - } - } - } - return Pair(lu, IntTensor(intArrayOf(m), pivot)) - } - - override fun luUnpack(lu: RealTensor, pivots: IntTensor): Triple { - // todo checks - val n = lu.shape[0] - val p = zeroesLike(lu) - pivots.buffer.array.forEachIndexed { i, pivot -> - p[i, pivot] = 1.0 - } - val l = zeroesLike(lu) - val u = zeroesLike(lu) - - for (i in 0 until n){ - for (j in 0 until n){ - if (i == j) { - l[i, j] = 1.0 - } - if (j < i) { - l[i, j] = lu[i, j] - } - if (j >= i) { - u[i, j] = lu[i, j] - } - } - } - return Triple(p, l, u) - } - - override fun RealTensor.svd(): Triple { - /** - * Main first task for @AlyaNovikova - */ + override fun RealTensor.std(dim: Int, unbiased: Boolean, keepDim: Boolean): RealTensor { TODO("Not yet implemented") } - override fun RealTensor.symEig(eigenvectors: Boolean): Pair { + override fun RealTensor.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): RealTensor { + TODO("Not yet implemented") + } + + override fun RealTensor.histc(bins: Int, min: Double, max: Double): RealTensor { TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 280acf8ea..a53054e21 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -5,11 +5,17 @@ public interface TensorAlgebra> { public fun TensorType.value(): T - public fun eye(n: Int): TensorType public fun zeros(shape: IntArray): TensorType - public fun zeroesLike(other: TensorType): TensorType + public fun TensorType.zeroesLike(): TensorType public fun ones(shape: IntArray): TensorType - public fun onesLike(shape: IntArray): TensorType + public fun TensorType.onesLike(): TensorType + + + //https://pytorch.org/docs/stable/generated/torch.full.html + public fun full(shape: IntArray, value: T): TensorType + + //https://pytorch.org/docs/stable/generated/torch.full_like.html#torch.full_like + public fun TensorType.fullLike(value: T): TensorType public fun TensorType.copy(): TensorType @@ -33,15 +39,6 @@ public interface TensorAlgebra> { public operator fun TensorType.unaryMinus(): TensorType - //https://pytorch.org/docs/stable/generated/torch.matmul.html - public infix fun TensorType.dot(other: TensorType): TensorType - - //https://pytorch.org/docs/stable/generated/torch.diag_embed.html - public fun diagonalEmbedding( - diagonalEntries: TensorType, - offset: Int = 0, dim1: Int = -2, dim2: Int = -1 - ): TensorType - //https://pytorch.org/docs/stable/generated/torch.transpose.html public fun TensorType.transpose(i: Int, j: Int): TensorType @@ -53,35 +50,45 @@ public interface TensorAlgebra> { public fun TensorType.abs(): TensorType //https://pytorch.org/docs/stable/generated/torch.sum.html - public fun TensorType.sum(): TensorType + public fun TensorType.sum(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cumsum.html#torch.cumsum + public fun TensorType.cumsum(dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.prod.html#torch.prod + public fun TensorType.prod(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cumprod.html#torch.cumprod + public fun TensorType.cumprod(dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.max.html#torch.max + public fun TensorType.max(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cummax.html#torch.cummax + public fun TensorType.cummax(dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.min.html#torch.min + public fun TensorType.min(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cummin.html#torch.cummin + public fun TensorType.cummin(dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.median.html#torch.median + public fun TensorType.median(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.maximum.html#torch.maximum + public fun maximum(lhs: TensorType, rhs: TensorType) + + //https://pytorch.org/docs/stable/generated/torch.minimum.html#torch.minimum + public fun minimum(lhs: TensorType, rhs: TensorType) + + //https://pytorch.org/docs/stable/generated/torch.sort.html#torch.sort + public fun TensorType.sort(dim: Int, keepDim: Boolean, descending: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cat.html#torch.cat + public fun cat(tensors: List, dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.flatten.html#torch.flatten + public fun TensorType.flatten(startDim: Int, endDim: Int): TensorType + } - -// https://proofwiki.org/wiki/Definition:Division_Algebra -public interface TensorPartialDivisionAlgebra> : - TensorAlgebra { - - public operator fun TensorType.div(value: T): TensorType - public operator fun TensorType.div(other: TensorType): TensorType - public operator fun TensorType.divAssign(value: T) - public operator fun TensorType.divAssign(other: TensorType) - - //https://pytorch.org/docs/stable/generated/torch.exp.html - public fun TensorType.exp(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.log.html - public fun TensorType.log(): TensorType - - // todo change type of pivots - //https://pytorch.org/docs/stable/generated/torch.lu.html - public fun TensorType.lu(): Pair - - //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun luUnpack(A_LU: TensorType, pivots: IntTensor): Triple - - //https://pytorch.org/docs/stable/generated/torch.svd.html - public fun TensorType.svd(): Triple - - //https://pytorch.org/docs/stable/generated/torch.symeig.html - public fun TensorType.symEig(eigenvectors: Boolean = true): Pair - -} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt new file mode 100644 index 000000000..2d448fa8c --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -0,0 +1,27 @@ +package space.kscience.kmath.tensors + +// https://proofwiki.org/wiki/Definition:Division_Algebra +public interface TensorPartialDivisionAlgebra> : + TensorAlgebra { + + public operator fun TensorType.div(value: T): TensorType + public operator fun TensorType.div(other: TensorType): TensorType + public operator fun TensorType.divAssign(value: T) + public operator fun TensorType.divAssign(other: TensorType) + + //https://pytorch.org/docs/stable/generated/torch.mean.html#torch.mean + public fun TensorType.mean(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.quantile.html#torch.quantile + public fun TensorType.quantile(q: T, dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.std.html#torch.std + public fun TensorType.std(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var + public fun TensorType.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.histc.html#torch.histc + public fun TensorType.histc(bins: Int, min: T, max: T): TensorType + +} From 39a088912346078f3c3647ac262b2cf8c490aa4a Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 07:50:20 +0000 Subject: [PATCH 076/393] Dev merge assemble fixed, tests still broken --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 2 +- .../tensors/RealAnalyticTensorAlgebra.kt | 4 +- .../tensors/RealLinearOpsTensorAlgebra.kt | 7 +-- .../kmath/tensors/RealTensorAlgebra.kt | 46 +++++++++---------- .../space/kscience/kmath/tensors/utils.kt | 4 +- .../kscience/kmath/tensors/TestRealTensor.kt | 4 +- .../kmath/tensors/TestRealTensorAlgebra.kt | 26 +++++------ 7 files changed, 48 insertions(+), 45 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index bd9cbfd45..db1135a33 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -32,7 +32,7 @@ public interface LinearOpsTensorAlgebra> : public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun luPivot(aLU: TensorType, pivots: IntTensor): Triple + public fun luPivot(lu: TensorType, pivots: IntTensor): Triple //https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd public fun TensorType.svd(): Triple diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt index cfecac0f4..a93ebcb89 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt @@ -144,5 +144,7 @@ public class RealAnalyticTensorAlgebra: TODO("Not yet implemented") } +} -} \ No newline at end of file +public inline fun RealAnalyticTensorAlgebra(block: RealTensorAlgebra.() -> R): R = + RealAnalyticTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt index 18c2050c0..98a5e581f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.array +import space.kscience.kmath.structures.toDoubleArray +import space.kscience.kmath.structures.toIntArray public class RealLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -80,7 +81,7 @@ public class RealLinearOpsTensorAlgebra : // todo checks val n = lu.shape[0] val p = lu.zeroesLike() - pivots.buffer.array.forEachIndexed { i, pivot -> + pivots.buffer.toIntArray().forEachIndexed { i, pivot -> p[i, pivot] = 1.0 } val l = lu.zeroesLike() @@ -130,4 +131,4 @@ public class RealLinearOpsTensorAlgebra : } public inline fun RealLinearOpsTensorAlgebra(block: RealTensorAlgebra.() -> R): R = - RealTensorAlgebra().block() \ No newline at end of file + RealLinearOpsTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 05e2b57d2..10cc0edad 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.array +import space.kscience.kmath.structures.toDoubleArray public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { @@ -9,7 +9,7 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.array[i] + this + other.buffer.toDoubleArray()[i] + this } return RealTensor(other.shape, resBuffer) } @@ -50,34 +50,34 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.array[i] + newOther.buffer.array[i] + newThis.buffer.toDoubleArray()[i] + newOther.buffer.toDoubleArray()[i] } return RealTensor(newThis.shape, resBuffer) } override fun RealTensor.plusAssign(value: Double) { - for (i in this.buffer.array.indices) { - this.buffer.array[i] += value + for (i in this.buffer.toDoubleArray().indices) { + this.buffer.toDoubleArray()[i] += value } } override fun RealTensor.plusAssign(other: RealTensor) { //todo should be change with broadcasting - for (i in this.buffer.array.indices) { - this.buffer.array[i] += other.buffer.array[i] + for (i in this.buffer.toDoubleArray().indices) { + this.buffer.toDoubleArray()[i] += other.buffer.toDoubleArray()[i] } } override fun Double.minus(other: RealTensor): RealTensor { val resBuffer = DoubleArray(other.buffer.size) { i -> - this - other.buffer.array[i] + this - other.buffer.toDoubleArray()[i] } return RealTensor(other.shape, resBuffer) } override fun RealTensor.minus(value: Double): RealTensor { val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.array[i] - value + this.buffer.toDoubleArray()[i] - value } return RealTensor(this.shape, resBuffer) } @@ -87,14 +87,14 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.array[i] - newOther.buffer.array[i] + newThis.buffer.toDoubleArray()[i] - newOther.buffer.toDoubleArray()[i] } return RealTensor(newThis.shape, resBuffer) } override fun RealTensor.minusAssign(value: Double) { - for (i in this.buffer.array.indices) { - this.buffer.array[i] -= value + for (i in this.buffer.toDoubleArray().indices) { + this.buffer.toDoubleArray()[i] -= value } } @@ -105,7 +105,7 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.array[i] * this + other.buffer.toDoubleArray()[i] * this } return RealTensor(other.shape, resBuffer) } @@ -116,28 +116,28 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - this.buffer.array[i] * other.buffer.array[i] + this.buffer.toDoubleArray()[i] * other.buffer.toDoubleArray()[i] } return RealTensor(this.shape, resBuffer) } override fun RealTensor.timesAssign(value: Double) { //todo should be change with broadcasting - for (i in this.buffer.array.indices) { - this.buffer.array[i] *= value + for (i in this.buffer.toDoubleArray().indices) { + this.buffer.toDoubleArray()[i] *= value } } override fun RealTensor.timesAssign(other: RealTensor) { //todo should be change with broadcasting - for (i in this.buffer.array.indices) { - this.buffer.array[i] *= other.buffer.array[i] + for (i in this.buffer.toDoubleArray().indices) { + this.buffer.toDoubleArray()[i] *= other.buffer.toDoubleArray()[i] } } override fun RealTensor.unaryMinus(): RealTensor { val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.array[i].unaryMinus() + this.buffer.toDoubleArray()[i].unaryMinus() } return RealTensor(this.shape, resBuffer) } @@ -158,14 +158,14 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra Date: Mon, 15 Mar 2021 08:31:19 +0000 Subject: [PATCH 077/393] Fixed tests with unsafe accessors --- .../kscience/kmath/structures/FloatBuffer.kt | 8 ++++ .../kscience/kmath/structures/IntBuffer.kt | 8 ++++ .../kscience/kmath/structures/LongBuffer.kt | 8 ++++ .../kscience/kmath/structures/RealBuffer.kt | 8 ++++ .../tensors/RealLinearOpsTensorAlgebra.kt | 5 +- .../kmath/tensors/RealTensorAlgebra.kt | 46 +++++++++---------- .../space/kscience/kmath/tensors/utils.kt | 4 +- 7 files changed, 59 insertions(+), 28 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt index 9fc7d55f3..dbcf35504 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt @@ -43,6 +43,14 @@ public fun Buffer.toFloatArray(): FloatArray = when(this) { else -> FloatArray(size, ::get) } +/** + * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. + */ +public fun Buffer.unsafeToFloatArray(): FloatArray = when(this) { + is FloatBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to FloatArray") +} + /** * Returns [FloatBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt index d3d0f79a5..d58451bc4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt @@ -42,6 +42,14 @@ public fun Buffer.toIntArray(): IntArray = when(this) { else -> IntArray(size, ::get) } +/** + * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. + */ +public fun Buffer.unsafeToIntArray(): IntArray = when(this) { + is IntBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to IntArray") +} + /** * Returns [IntBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt index fec358421..3fa9bf861 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt @@ -42,6 +42,14 @@ public fun Buffer.toLongArray(): LongArray = when(this) { else -> LongArray(size, ::get) } +/** + * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. + */ +public fun Buffer.unsafeToLongArray(): LongArray = when(this) { + is LongBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to LongArray") +} + /** * Returns [LongBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt index 01b533138..69e1ae9cd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt @@ -47,6 +47,14 @@ public fun Buffer.toDoubleArray(): DoubleArray = when(this) { else -> DoubleArray(size, ::get) } +/** + * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. + */ +public fun Buffer.unsafeToDoubleArray(): DoubleArray = when(this) { + is RealBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") +} + /** * Returns [RealBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt index 98a5e581f..f73e4c4cd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt @@ -1,7 +1,6 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.toDoubleArray -import space.kscience.kmath.structures.toIntArray +import space.kscience.kmath.structures.unsafeToIntArray public class RealLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -81,7 +80,7 @@ public class RealLinearOpsTensorAlgebra : // todo checks val n = lu.shape[0] val p = lu.zeroesLike() - pivots.buffer.toIntArray().forEachIndexed { i, pivot -> + pivots.buffer.unsafeToIntArray().forEachIndexed { i, pivot -> p[i, pivot] = 1.0 } val l = lu.zeroesLike() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index 10cc0edad..ee0733577 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.toDoubleArray +import space.kscience.kmath.structures.unsafeToDoubleArray public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { @@ -9,7 +9,7 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.toDoubleArray()[i] + this + other.buffer.unsafeToDoubleArray()[i] + this } return RealTensor(other.shape, resBuffer) } @@ -50,34 +50,34 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.toDoubleArray()[i] + newOther.buffer.toDoubleArray()[i] + newThis.buffer.unsafeToDoubleArray()[i] + newOther.buffer.unsafeToDoubleArray()[i] } return RealTensor(newThis.shape, resBuffer) } override fun RealTensor.plusAssign(value: Double) { - for (i in this.buffer.toDoubleArray().indices) { - this.buffer.toDoubleArray()[i] += value + for (i in this.buffer.unsafeToDoubleArray().indices) { + this.buffer.unsafeToDoubleArray()[i] += value } } override fun RealTensor.plusAssign(other: RealTensor) { //todo should be change with broadcasting - for (i in this.buffer.toDoubleArray().indices) { - this.buffer.toDoubleArray()[i] += other.buffer.toDoubleArray()[i] + for (i in this.buffer.unsafeToDoubleArray().indices) { + this.buffer.unsafeToDoubleArray()[i] += other.buffer.unsafeToDoubleArray()[i] } } override fun Double.minus(other: RealTensor): RealTensor { val resBuffer = DoubleArray(other.buffer.size) { i -> - this - other.buffer.toDoubleArray()[i] + this - other.buffer.unsafeToDoubleArray()[i] } return RealTensor(other.shape, resBuffer) } override fun RealTensor.minus(value: Double): RealTensor { val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.toDoubleArray()[i] - value + this.buffer.unsafeToDoubleArray()[i] - value } return RealTensor(this.shape, resBuffer) } @@ -87,14 +87,14 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.toDoubleArray()[i] - newOther.buffer.toDoubleArray()[i] + newThis.buffer.unsafeToDoubleArray()[i] - newOther.buffer.unsafeToDoubleArray()[i] } return RealTensor(newThis.shape, resBuffer) } override fun RealTensor.minusAssign(value: Double) { - for (i in this.buffer.toDoubleArray().indices) { - this.buffer.toDoubleArray()[i] -= value + for (i in this.buffer.unsafeToDoubleArray().indices) { + this.buffer.unsafeToDoubleArray()[i] -= value } } @@ -105,7 +105,7 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.toDoubleArray()[i] * this + other.buffer.unsafeToDoubleArray()[i] * this } return RealTensor(other.shape, resBuffer) } @@ -116,28 +116,28 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra - this.buffer.toDoubleArray()[i] * other.buffer.toDoubleArray()[i] + this.buffer.unsafeToDoubleArray()[i] * other.buffer.unsafeToDoubleArray()[i] } return RealTensor(this.shape, resBuffer) } override fun RealTensor.timesAssign(value: Double) { //todo should be change with broadcasting - for (i in this.buffer.toDoubleArray().indices) { - this.buffer.toDoubleArray()[i] *= value + for (i in this.buffer.unsafeToDoubleArray().indices) { + this.buffer.unsafeToDoubleArray()[i] *= value } } override fun RealTensor.timesAssign(other: RealTensor) { //todo should be change with broadcasting - for (i in this.buffer.toDoubleArray().indices) { - this.buffer.toDoubleArray()[i] *= other.buffer.toDoubleArray()[i] + for (i in this.buffer.unsafeToDoubleArray().indices) { + this.buffer.unsafeToDoubleArray()[i] *= other.buffer.unsafeToDoubleArray()[i] } } override fun RealTensor.unaryMinus(): RealTensor { val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.toDoubleArray()[i].unaryMinus() + this.buffer.unsafeToDoubleArray()[i].unaryMinus() } return RealTensor(this.shape, resBuffer) } @@ -158,14 +158,14 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra Date: Mon, 15 Mar 2021 08:48:31 +0000 Subject: [PATCH 078/393] unsafe buffer casts moved to internal utils --- .../kscience/kmath/structures/FloatBuffer.kt | 8 ----- .../kscience/kmath/structures/IntBuffer.kt | 8 ----- .../kscience/kmath/structures/LongBuffer.kt | 8 ----- .../kscience/kmath/structures/RealBuffer.kt | 8 ----- .../tensors/RealLinearOpsTensorAlgebra.kt | 2 -- .../kmath/tensors/RealTensorAlgebra.kt | 2 -- .../space/kscience/kmath/tensors/utils.kt | 36 +++++++++++++++++-- .../kmath/tensors/TestRealTensorAlgebra.kt | 26 +++++++------- 8 files changed, 47 insertions(+), 51 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt index dbcf35504..9fc7d55f3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt @@ -43,14 +43,6 @@ public fun Buffer.toFloatArray(): FloatArray = when(this) { else -> FloatArray(size, ::get) } -/** - * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. - */ -public fun Buffer.unsafeToFloatArray(): FloatArray = when(this) { - is FloatBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to FloatArray") -} - /** * Returns [FloatBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt index d58451bc4..d3d0f79a5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt @@ -42,14 +42,6 @@ public fun Buffer.toIntArray(): IntArray = when(this) { else -> IntArray(size, ::get) } -/** - * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. - */ -public fun Buffer.unsafeToIntArray(): IntArray = when(this) { - is IntBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to IntArray") -} - /** * Returns [IntBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt index 3fa9bf861..fec358421 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt @@ -42,14 +42,6 @@ public fun Buffer.toLongArray(): LongArray = when(this) { else -> LongArray(size, ::get) } -/** - * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. - */ -public fun Buffer.unsafeToLongArray(): LongArray = when(this) { - is LongBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to LongArray") -} - /** * Returns [LongBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt index 69e1ae9cd..01b533138 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt @@ -47,14 +47,6 @@ public fun Buffer.toDoubleArray(): DoubleArray = when(this) { else -> DoubleArray(size, ::get) } -/** - * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. - */ -public fun Buffer.unsafeToDoubleArray(): DoubleArray = when(this) { - is RealBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") -} - /** * Returns [RealBuffer] over this array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt index f73e4c4cd..dcd740356 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt @@ -1,7 +1,5 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.unsafeToIntArray - public class RealLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, RealTensorAlgebra() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt index ee0733577..83a513a7a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt @@ -1,7 +1,5 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.unsafeToDoubleArray - public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt index 04b4ddcbf..b03fb7dd7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.unsafeToDoubleArray +import space.kscience.kmath.structures.* import kotlin.math.max @@ -93,4 +93,36 @@ internal inline fun , internal inline fun , TorchTensorAlgebraType : TensorAlgebra> TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = - check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) \ No newline at end of file + check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) + +/** + * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.unsafeToIntArray(): IntArray = when(this) { + is IntBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to IntArray") +} + +/** + * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.unsafeToLongArray(): LongArray = when(this) { + is LongBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to LongArray") +} + +/** + * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.unsafeToFloatArray(): FloatArray = when(this) { + is FloatBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to FloatArray") +} + +/** + * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.unsafeToDoubleArray(): DoubleArray = when(this) { + is RealBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") +} diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index 80e3c3eab..72bbf1787 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.structures.toDoubleArray + import kotlin.test.Test import kotlin.test.assertTrue @@ -10,7 +10,7 @@ class TestRealTensorAlgebra { fun doublePlus() = RealTensorAlgebra { val tensor = RealTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor - assertTrue(res.buffer.toDoubleArray() contentEquals doubleArrayOf(11.0,12.0)) + assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(11.0,12.0)) } @Test @@ -18,7 +18,7 @@ class TestRealTensorAlgebra { val tensor = RealTensor(intArrayOf(1), doubleArrayOf(0.0)) val res = tensor.transpose(0, 0) - assertTrue(res.buffer.toDoubleArray() contentEquals doubleArrayOf(0.0)) + assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(0.0)) assertTrue(res.shape contentEquals intArrayOf(1)) } @@ -27,7 +27,7 @@ class TestRealTensorAlgebra { val tensor = RealTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) - assertTrue(res.buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) + assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) assertTrue(res.shape contentEquals intArrayOf(2, 3)) } @@ -42,9 +42,9 @@ class TestRealTensorAlgebra { assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2)) - assertTrue(res01.buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res02.buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) - assertTrue(res12.buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res01.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res02.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res12.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) } @Test @@ -70,9 +70,9 @@ class TestRealTensorAlgebra { assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[0].buffer.toDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res[1].buffer.toDoubleArray() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) - assertTrue(res[2].buffer.toDoubleArray() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) + assertTrue(res[0].buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + assertTrue(res[2].buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) } @Test @@ -82,14 +82,14 @@ class TestRealTensorAlgebra { val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) assertTrue((tensor2 - tensor1).shape contentEquals intArrayOf(2, 3)) - assertTrue((tensor2 - tensor1).buffer.toDoubleArray() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) + assertTrue((tensor2 - tensor1).buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) assertTrue((tensor3 - tensor1).shape contentEquals intArrayOf(1, 2, 3)) - assertTrue((tensor3 - tensor1).buffer.toDoubleArray() + assertTrue((tensor3 - tensor1).buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0)) assertTrue((tensor3 - tensor2).shape contentEquals intArrayOf(1, 1, 3)) - assertTrue((tensor3 - tensor2).buffer.toDoubleArray() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) + assertTrue((tensor3 - tensor2).buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) } } \ No newline at end of file From 0e0deaeb72d0ecc4cb6acb7fa6a1409b249f555b Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 15 Mar 2021 14:26:17 +0300 Subject: [PATCH 079/393] Refactor buffer factories --- CHANGELOG.md | 2 +- kmath-core/api/kmath-core.api | 17 +- ...rLinearSpace.kt => BufferedLinearSpace.kt} | 2 +- .../kscience/kmath/linear/LinearSolver.kt | 13 +- .../kscience/kmath/linear/LinearSpace.kt | 5 +- .../kscience/kmath/linear/LupDecomposition.kt | 6 +- .../space/kscience/kmath/nd/NDStructure.kt | 4 +- .../space/kscience/kmath/nd/RealNDField.kt | 3 +- .../space/kscience/kmath/nd/Structure1D.kt | 9 ++ .../space/kscience/kmath/nd/Structure2D.kt | 7 +- .../space/kscience/kmath/structures/Buffer.kt | 150 +++++++----------- .../kmath/structures/bufferOperation.kt | 79 ++++++++- .../space/kscience/kmath/real/RealVector.kt | 7 +- .../kaceince/kmath/real/RealVectorTest.kt | 12 +- .../kscience/kmath/histogram/Histogram.kt | 4 +- .../space/kscience/kmath/stat/Distribution.kt | 3 +- 16 files changed, 198 insertions(+), 125 deletions(-) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/{BufferLinearSpace.kt => BufferedLinearSpace.kt} (98%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47690e36a..eb97698c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ - Exponential operations merged with hyperbolic functions - Space is replaced by Group. Space is reserved for vector spaces. - VectorSpace is now a vector space -- +- Buffer factories for primitives moved to MutableBuffer.Companion ### Deprecated diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 2fa9e165b..c5e13fe20 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -432,7 +432,7 @@ public final class space/kscience/kmath/expressions/SymbolIndexerKt { public static final fun withSymbols ([Lspace/kscience/kmath/expressions/Symbol;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } -public final class space/kscience/kmath/linear/BufferLinearSpace : space/kscience/kmath/linear/LinearSpace { +public final class space/kscience/kmath/linear/BufferedLinearSpace : space/kscience/kmath/linear/LinearSpace { public fun (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V public fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D; public fun buildVector (ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; @@ -2115,7 +2115,6 @@ public abstract interface class space/kscience/kmath/structures/Buffer { public final class space/kscience/kmath/structures/Buffer$Companion { public final fun auto (Lkotlin/reflect/KClass;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; public final fun boxing (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; - public final fun real-8hrHhI4 (ILkotlin/jvm/functions/Function1;)[D } public final class space/kscience/kmath/structures/Buffer$DefaultImpls { @@ -2123,15 +2122,17 @@ public final class space/kscience/kmath/structures/Buffer$DefaultImpls { } public final class space/kscience/kmath/structures/BufferKt { - public static final fun ListBuffer (ILkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun asBuffer (Ljava/util/List;)Ljava/util/List; public static final fun asBuffer ([Ljava/lang/Object;)Lspace/kscience/kmath/structures/ArrayBuffer; - public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable; + public static final fun asMutableBuffer (Ljava/util/List;)Ljava/util/List; public static final fun asReadOnly (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence; public static final fun getIndices (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/ranges/IntRange; +} + +public final class space/kscience/kmath/structures/BufferOperationKt { + public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable; + public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence; public static final fun toList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List; - public static final fun toMutableList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List; } public abstract interface class space/kscience/kmath/structures/FlaggedBuffer : space/kscience/kmath/structures/Buffer { @@ -2316,7 +2317,11 @@ public abstract interface class space/kscience/kmath/structures/MutableBuffer : public final class space/kscience/kmath/structures/MutableBuffer$Companion { public final fun auto (Lkotlin/reflect/KClass;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableBuffer; public final fun boxing (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableBuffer; + public final fun float-YxruXGw (ILkotlin/jvm/functions/Function1;)[F + public final fun int-Ye6GY2U (ILkotlin/jvm/functions/Function1;)[I + public final fun long-BuQOeTY (ILkotlin/jvm/functions/Function1;)[J public final fun real-8hrHhI4 (ILkotlin/jvm/functions/Function1;)[D + public final fun short-1yRgbGw (ILkotlin/jvm/functions/Function1;)[S } public final class space/kscience/kmath/structures/MutableBuffer$DefaultImpls { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt similarity index 98% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt index b6c2ea17b..5814ab35c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.structures.VirtualBuffer import space.kscience.kmath.structures.indices -public class BufferLinearSpace>( +public class BufferedLinearSpace>( override val elementAlgebra: A, private val bufferFactory: BufferFactory, ) : LinearSpace { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt index 6cce5a446..af136c552 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt @@ -6,9 +6,20 @@ import space.kscience.kmath.nd.as1D * A group of methods to resolve equation A dot X = B, where A and B are matrices or vectors */ public interface LinearSolver { + /** + * Solve a dot x = b matrix equation and return x + */ public fun solve(a: Matrix, b: Matrix): Matrix + + /** + * Solve a dot x = b vector equation and return b + */ public fun solve(a: Matrix, b: Point): Point = solve(a, b.asMatrix()).asVector() - public fun inverse(a: Matrix): Matrix + + /** + * Get inverse of a matrix + */ + public fun inverse(matrix: Matrix): Matrix } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 1642bfb14..cf8564e08 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -5,6 +5,7 @@ import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory +import space.kscience.kmath.structures.RealBuffer import kotlin.reflect.KClass /** @@ -174,9 +175,9 @@ public interface LinearSpace> { public fun > buffered( algebra: A, bufferFactory: BufferFactory = Buffer.Companion::boxing, - ): LinearSpace = BufferLinearSpace(algebra,bufferFactory) + ): LinearSpace = BufferedLinearSpace(algebra,bufferFactory) - public val real: LinearSpace = buffered(RealField, Buffer.Companion::real) + public val real: LinearSpace = buffered(RealField, ::RealBuffer) /** * Automatic buffered matrix, unboxed if it is possible diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt index 0937f1e19..eed50ec28 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt @@ -3,10 +3,10 @@ package space.kscience.kmath.linear import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.getFeature import space.kscience.kmath.operations.* -import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferAccessor2D import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableBufferFactory +import space.kscience.kmath.structures.RealBuffer /** * Common implementation of [LupDecompositionFeature]. @@ -152,7 +152,7 @@ public inline fun > LinearSpace>.lup( ): LupDecomposition = lup(MutableBuffer.Companion::auto, matrix, checkSingular) public fun LinearSpace.lup(matrix: Matrix): LupDecomposition = - lup(Buffer.Companion::real, matrix) { it < 1e-11 } + lup(::RealBuffer, matrix) { it < 1e-11 } public fun LupDecomposition.solveWithLup( factory: MutableBufferFactory, @@ -230,7 +230,7 @@ public inline fun > LinearSpace>.inverseWi @OptIn(UnstableKMathAPI::class) public fun LinearSpace.solveWithLup(a: Matrix, b: Matrix): Matrix { // Use existing decomposition if it is provided by matrix - val bufferFactory: MutableBufferFactory = MutableBuffer.Companion::real + val bufferFactory: MutableBufferFactory = ::RealBuffer val decomposition: LupDecomposition = a.getFeature() ?: lup(bufferFactory, a) { it < 1e-11 } return decomposition.solveWithLup(bufferFactory, b) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt index 48041df58..d758f195d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt @@ -48,8 +48,8 @@ public interface NDStructure { public override fun hashCode(): Int /** - * Feature is additional property or hint that does not directly affect the structure, but could in some cases help - * optimize operations and performance. If the feature is not present, null is defined. + * Feature is some additional strucure information which allows to access it special properties or hints. + * If the feature is not present, null is returned. */ @UnstableKMathAPI public fun getFeature(type: KClass): F? = null diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt index 2165aea22..9f1f14af1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt @@ -5,7 +5,6 @@ import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.NumbersAddOperations import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.RealBuffer import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -13,7 +12,7 @@ import kotlin.contracts.contract @OptIn(UnstableKMathAPI::class) public class RealNDField( shape: IntArray, -) : BufferedNDField(shape, RealField, Buffer.Companion::real), +) : BufferedNDField(shape, RealField, ::RealBuffer), NumbersAddOperations>, ScaleOperations>, ExtendedField> { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 1335a4933..ac8714803 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -56,3 +56,12 @@ public fun NDStructure.as1D(): Structure1D = this as? Structure1D ? * Represent this buffer as 1D structure */ public fun Buffer.asND(): Structure1D = Buffer1DWrapper(this) + +/** + * Expose inner buffer of this [Structure1D] if possible + */ +internal fun Structure1D.unwrap(): Buffer = when { + this is Buffer1DWrapper -> buffer + this is Structure1DWrapper && structure is NDBuffer -> structure.buffer + else -> this +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index e9f8234e5..60dedc933 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -86,4 +86,9 @@ public fun NDStructure.as2D(): Structure2D = this as? Structure2D ? else -> error("Can't create 2d-structure from ${shape.size}d-structure") } -internal fun Structure2D.unwrap(): NDStructure = if (this is Structure2DWrapper) structure else this \ No newline at end of file +/** + * Expose inner [NDStructure] if possible + */ +internal fun Structure2D.unwrap(): NDStructure = + if (this is Structure2DWrapper) structure + else this \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 2bde18fce..1d40a2f2e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -44,21 +44,12 @@ public interface Buffer { asSequence().mapIndexed { index, value -> value == other[index] }.all { it } public companion object { - /** - * Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified - * [initializer] function. - */ - public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer = - RealBuffer(size) { initializer(it) } - /** * Creates a [ListBuffer] of given type [T] with given [size]. Each element is calculated by calling the * specified [initializer] function. */ public inline fun boxing(size: Int, initializer: (Int) -> T): Buffer = - ListBuffer(List(size, initializer)) - - // TODO add resolution based on Annotation or companion resolution + List(size, initializer).asBuffer() /** * Creates a [Buffer] of given [type]. If the type is primitive, specialized buffers are used ([IntBuffer], @@ -69,11 +60,11 @@ public interface Buffer { @Suppress("UNCHECKED_CAST") public inline fun auto(type: KClass, size: Int, initializer: (Int) -> T): Buffer = when (type) { - Double::class -> RealBuffer(size) { initializer(it) as Double } as Buffer - Short::class -> ShortBuffer(size) { initializer(it) as Short } as Buffer - Int::class -> IntBuffer(size) { initializer(it) as Int } as Buffer - Long::class -> LongBuffer(size) { initializer(it) as Long } as Buffer - Float::class -> FloatBuffer(size) { initializer(it) as Float } as Buffer + Double::class -> MutableBuffer.real(size) { initializer(it) as Double } as Buffer + Short::class -> MutableBuffer.short(size) { initializer(it) as Short } as Buffer + Int::class -> MutableBuffer.int(size) { initializer(it) as Int } as Buffer + Long::class -> MutableBuffer.long(size) { initializer(it) as Long } as Buffer + Float::class -> MutableBuffer.float(size) { initializer(it) as Float } as Buffer else -> boxing(size, initializer) } @@ -89,41 +80,6 @@ public interface Buffer { } } -/** - * Creates a sequence that returns all elements from this [Buffer]. - */ -public fun Buffer.asSequence(): Sequence = Sequence(::iterator) - -/** - * Creates an iterable that returns all elements from this [Buffer]. - */ -public fun Buffer.asIterable(): Iterable = Iterable(::iterator) - -/** - * Returns a new [List] containing all elements of this buffer. - */ -public fun Buffer.toList(): List = when (this) { - is ArrayBuffer -> array.toList() - is ListBuffer -> list.toList() - is MutableListBuffer -> list.toList() - else -> asSequence().toList() -} - -/** - * Returns a new [MutableList] filled with all elements of this buffer. - */ -public fun Buffer.toMutableList(): MutableList = when (this) { - is ArrayBuffer -> array.toMutableList() - is ListBuffer -> list.toMutableList() - is MutableListBuffer -> list.toMutableList() - else -> asSequence().toMutableList() -} - -/** - * Returns a new [Array] containing all elements of this buffer. - */ -public inline fun Buffer.toTypedArray(): Array = asSequence().toList().toTypedArray() - /** * Returns an [IntRange] of the valid indices for this [Buffer]. */ @@ -146,6 +102,44 @@ public interface MutableBuffer : Buffer { public fun copy(): MutableBuffer public companion object { + + /** + * Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified + * [initializer] function. + */ + public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer = + RealBuffer(size, initializer) + + /** + * Creates a [ShortBuffer] with the specified [size], where each element is calculated by calling the specified + * [initializer] function. + */ + public inline fun short(size: Int, initializer: (Int) -> Short): ShortBuffer = + ShortBuffer(size, initializer) + + /** + * Creates a [IntBuffer] with the specified [size], where each element is calculated by calling the specified + * [initializer] function. + */ + public inline fun int(size: Int, initializer: (Int) -> Int): IntBuffer = + IntBuffer(size, initializer) + + /** + * Creates a [LongBuffer] with the specified [size], where each element is calculated by calling the specified + * [initializer] function. + */ + public inline fun long(size: Int, initializer: (Int) -> Long): LongBuffer = + LongBuffer(size, initializer) + + + /** + * Creates a [FloatBuffer] with the specified [size], where each element is calculated by calling the specified + * [initializer] function. + */ + public inline fun float(size: Int, initializer: (Int) -> Float): FloatBuffer = + FloatBuffer(size, initializer) + + /** * Create a boxing mutable buffer of given type */ @@ -161,11 +155,11 @@ public interface MutableBuffer : Buffer { @Suppress("UNCHECKED_CAST") public inline fun auto(type: KClass, size: Int, initializer: (Int) -> T): MutableBuffer = when (type) { - Double::class -> RealBuffer(size) { initializer(it) as Double } as MutableBuffer - Short::class -> ShortBuffer(size) { initializer(it) as Short } as MutableBuffer - Int::class -> IntBuffer(size) { initializer(it) as Int } as MutableBuffer - Float::class -> FloatBuffer(size) { initializer(it) as Float } as MutableBuffer - Long::class -> LongBuffer(size) { initializer(it) as Long } as MutableBuffer + Double::class -> real(size) { initializer(it) as Double } as MutableBuffer + Short::class -> short(size) { initializer(it) as Short } as MutableBuffer + Int::class -> int(size) { initializer(it) as Int } as MutableBuffer + Float::class -> float(size) { initializer(it) as Float } as MutableBuffer + Long::class -> long(size) { initializer(it) as Long } as MutableBuffer else -> boxing(size, initializer) } @@ -178,13 +172,6 @@ public interface MutableBuffer : Buffer { @Suppress("UNCHECKED_CAST") public inline fun auto(size: Int, initializer: (Int) -> T): MutableBuffer = auto(T::class, size, initializer) - - /** - * Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified - * [initializer] function. - */ - public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer = - RealBuffer(size) { initializer(it) } } } @@ -207,15 +194,6 @@ public inline class ListBuffer(public val list: List) : Buffer { */ public fun List.asBuffer(): ListBuffer = ListBuffer(this) -/** - * Creates a new [ListBuffer] with the specified [size], where each element is calculated by calling the specified - * [init] function. - * - * The function [init] is called for each array element sequentially starting from the first one. - * It should return the value for an array element given its index. - */ -public inline fun ListBuffer(size: Int, init: (Int) -> T): ListBuffer = List(size, init).asBuffer() - /** * [MutableBuffer] implementation over [MutableList]. * @@ -236,6 +214,11 @@ public inline class MutableListBuffer(public val list: MutableList) : Muta override fun copy(): MutableBuffer = MutableListBuffer(ArrayList(list)) } +/** + * Returns an [ListBuffer] that wraps the original list. + */ +public fun MutableList.asMutableBuffer(): MutableListBuffer = MutableListBuffer(this) + /** * [MutableBuffer] implementation over [Array]. * @@ -244,8 +227,7 @@ public inline class MutableListBuffer(public val list: MutableList) : Muta */ public class ArrayBuffer(internal val array: Array) : MutableBuffer { // Can't inline because array is invariant - override val size: Int - get() = array.size + override val size: Int get() = array.size override operator fun get(index: Int): T = array[index] @@ -263,16 +245,6 @@ public class ArrayBuffer(internal val array: Array) : MutableBuffer { */ public fun Array.asBuffer(): ArrayBuffer = ArrayBuffer(this) -/** - * Creates a new [ArrayBuffer] with the specified [size], where each element is calculated by calling the specified - * [init] function. - * - * The function [init] is called for each array element sequentially starting from the first one. - * It should return the value for an array element given its index. - */ -public inline fun ArrayBuffer(size: Int, init: (Int) -> T): ArrayBuffer = - Array(size) { i -> init(i) }.asBuffer() - /** * Immutable wrapper for [MutableBuffer]. * @@ -313,14 +285,4 @@ public class VirtualBuffer(override val size: Int, private val generator: (In /** * Convert this buffer to read-only buffer. */ -public fun Buffer.asReadOnly(): Buffer = if (this is MutableBuffer) ReadOnlyBuffer(this) else this - -/** - * Typealias for buffer transformations. - */ -public typealias BufferTransform = (Buffer) -> Buffer - -/** - * Typealias for buffer transformations with suspend function. - */ -public typealias SuspendBufferTransform = suspend (Buffer) -> Buffer +public fun Buffer.asReadOnly(): Buffer = if (this is MutableBuffer) ReadOnlyBuffer(this) else this \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt index 459136631..4355ba17f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt @@ -1,7 +1,84 @@ package space.kscience.kmath.structures +import space.kscience.kmath.misc.UnstableKMathAPI +/** + * Typealias for buffer transformations. + */ +public typealias BufferTransform = (Buffer) -> Buffer + +/** + * Typealias for buffer transformations with suspend function. + */ +public typealias SuspendBufferTransform = suspend (Buffer) -> Buffer + + +/** + * Creates a sequence that returns all elements from this [Buffer]. + */ +public fun Buffer.asSequence(): Sequence = Sequence(::iterator) + +/** + * Creates an iterable that returns all elements from this [Buffer]. + */ +public fun Buffer.asIterable(): Iterable = Iterable(::iterator) + +/** + * Returns a new [List] containing all elements of this buffer. + */ +public fun Buffer.toList(): List = when (this) { + is ArrayBuffer -> array.toList() + is ListBuffer -> list.toList() + is MutableListBuffer -> list.toList() + else -> asSequence().toList() +} + +/** + * Returns a new [MutableList] filled with all elements of this buffer. + * **NOTE:** this method uses a protective copy, so it should not be used in performance-critical code. + */ +@UnstableKMathAPI +public fun Buffer.toMutableList(): MutableList = when (this) { + is ArrayBuffer -> array.toMutableList() + is ListBuffer -> list.toMutableList() + is MutableListBuffer -> list.toMutableList() + else -> MutableList(size, ::get) +} + +/** + * Returns a new [Array] containing all elements of this buffer. + * **NOTE:** this method uses a protective copy, so it should not be used in performance-critical code. + */ +@UnstableKMathAPI +public inline fun Buffer.toTypedArray(): Array = Array(size, ::get) + +/** + * Create a new buffer from this one with the given mapping function. + * Provided [BufferFactory] is used to construct the new buffer. + */ public inline fun Buffer.map( bufferFactory: BufferFactory = Buffer.Companion::auto, crossinline block: (T) -> R, -): Buffer = bufferFactory(size) { block(get(it)) } \ No newline at end of file +): Buffer = bufferFactory(size) { block(get(it)) } + +/** + * Create a new buffer from this one with the given indexed mapping function. + * Provided [BufferFactory] is used to construct the new buffer. + */ +public inline fun Buffer.mapIndexed( + bufferFactory: BufferFactory = Buffer.Companion::auto, + crossinline block: (index: Int, value: T) -> R, +): Buffer = bufferFactory(size) { block(it, get(it)) } + +/** + * Zip two buffers using given [transform]. + */ +@UnstableKMathAPI +public inline fun Buffer.zip( + other: Buffer, + bufferFactory: BufferFactory = Buffer.Companion::auto, + crossinline transform: (T1, T2) -> R, +): Buffer { + require(size == other.size) { "Buffer size mismatch in zip: expected $size but found ${other.size}" } + return bufferFactory(size) { transform(get(it), other[it]) } +} \ No newline at end of file diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt index ee42fe404..8cc128947 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt @@ -1,8 +1,10 @@ package space.kscience.kmath.real import space.kscience.kmath.linear.Point +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Norm import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.MutableBuffer.Companion.real import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.asIterable import space.kscience.kmath.structures.indices @@ -20,15 +22,16 @@ public operator fun Buffer.Companion.invoke(vararg doubles: Double): RealVector /** * Fill the vector of given [size] with given [value] */ +@UnstableKMathAPI public fun Buffer.Companion.same(size: Int, value: Number): RealVector = real(size) { value.toDouble() } // Transformation methods public inline fun RealVector.map(transform: (Double) -> Double): RealVector = - Buffer.real(size) { transform(get(it)) } + real(size) { transform(get(it)) } public inline fun RealVector.mapIndexed(transform: (index: Int, value: Double) -> Double): RealVector = - Buffer.real(size) { transform(it, get(it)) } + real(size) { transform(it, get(it)) } public operator fun RealVector.plus(other: RealVector): RealVector { require(size == other.size) { "Vector size $size expected but ${other.size} found" } diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt index 59d55110f..60d85fda3 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt @@ -4,30 +4,30 @@ import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.asMatrix import space.kscience.kmath.linear.transpose import space.kscience.kmath.real.plus -import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.RealBuffer import kotlin.test.Test import kotlin.test.assertEquals internal class RealVectorTest { @Test fun testSum() { - val vector1 = Buffer.real(5) { it.toDouble() } - val vector2 = Buffer.real(5) { 5 - it.toDouble() } + val vector1 = RealBuffer(5) { it.toDouble() } + val vector2 = RealBuffer(5) { 5 - it.toDouble() } val sum = vector1 + vector2 assertEquals(5.0, sum[2]) } @Test fun testVectorToMatrix() { - val vector = Buffer.real(5) { it.toDouble() } + val vector = RealBuffer(5) { it.toDouble() } val matrix = vector.asMatrix() assertEquals(4.0, matrix[4, 0]) } @Test fun testDot() { - val vector1 = Buffer.real(5) { it.toDouble() } - val vector2 = Buffer.real(5) { 5 - it.toDouble() } + val vector1 = RealBuffer(5) { it.toDouble() } + val vector2 = RealBuffer(5) { 5 - it.toDouble() } val matrix1 = vector1.asMatrix() val matrix2 = vector2.asMatrix().transpose() val product = LinearSpace.real.run { matrix1 dot matrix2 } diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt index 73b34783c..9ee4a6e1e 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt @@ -2,8 +2,8 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.Domain import space.kscience.kmath.linear.Point -import space.kscience.kmath.structures.ArrayBuffer import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.structures.asBuffer /** * The binned data element. Could be a histogram bin with a number of counts or an artificial construct @@ -40,7 +40,7 @@ public fun interface HistogramBuilder { public fun > HistogramBuilder.put(point: Point): Unit = putValue(point, 1.0) -public fun HistogramBuilder.put(vararg point: T): Unit = put(ArrayBuffer(point)) +public fun HistogramBuilder.put(vararg point: T): Unit = put(point.asBuffer()) public fun HistogramBuilder.put(vararg point: Number): Unit = put(RealBuffer(point.map { it.toDouble() }.toDoubleArray())) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt index fa38dd9e4..b5b6db1d8 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt @@ -4,6 +4,7 @@ import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.collect import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory +import space.kscience.kmath.structures.RealBuffer public interface Sampler { public fun sample(generator: RandomGenerator): Chain @@ -74,4 +75,4 @@ public fun Sampler.sampleBuffer( * Generate a bunch of samples from real distributions */ public fun Sampler.sampleBuffer(generator: RandomGenerator, size: Int): Chain> = - sampleBuffer(generator, size, Buffer.Companion::real) + sampleBuffer(generator, size, ::RealBuffer) From d9743978ab5739e087f23bbe1c86240231ca5b10 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 15 Mar 2021 14:26:59 +0300 Subject: [PATCH 080/393] Reformat code --- .../kmath/expressions/DifferentiableExpression.kt | 2 +- .../kscience/kmath/expressions/Expression.kt | 2 +- .../expressions/FunctionalExpressionAlgebra.kt | 2 +- .../kscience/kmath/linear/BufferedLinearSpace.kt | 2 +- .../space/kscience/kmath/linear/LinearSpace.kt | 2 +- .../space/kscience/kmath/linear/VirtualMatrix.kt | 2 +- .../kotlin/space/kscience/kmath/nd/NDAlgebra.kt | 15 ++++++++------- .../kscience/kmath/operations/AlgebraElements.kt | 2 +- .../kmath/operations/algebraExtensions.kt | 4 ++-- .../kscience/kmath/structures/BufferAccessor2D.kt | 4 ++-- .../kscience/kmath/structures/FloatBuffer.kt | 2 +- .../space/kscience/kmath/structures/IntBuffer.kt | 2 +- .../space/kscience/kmath/structures/LongBuffer.kt | 2 +- .../kscience/kmath/structures/MemoryBuffer.kt | 4 ++-- .../space/kscience/kmath/structures/RealBuffer.kt | 2 +- .../kscience/kmath/structures/ShortBuffer.kt | 2 +- .../kscience/kmath/linear/RealLUSolverTest.kt | 6 +++--- .../kmath/structures/NumberNDFieldTest.kt | 2 +- 18 files changed, 30 insertions(+), 29 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt index 508a62aca..5cbc4dbf4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt @@ -28,7 +28,7 @@ public fun > DifferentiableExpression.derivative(name /** * A [DifferentiableExpression] that defines only first derivatives */ -public abstract class FirstDerivativeExpression> : DifferentiableExpression { +public abstract class FirstDerivativeExpression> : DifferentiableExpression { /** * Returns first derivative of this expression by given [symbol]. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt index 231bbdab1..5ba24aa62 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt @@ -95,7 +95,7 @@ public fun ExpressionAlgebra.bindSymbol(symbol: Symbol): E = /** * A delegate to create a symbol with a string identity in this scope */ -public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> +public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> StringSymbol(property.name) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index 880f13a3e..cca75754f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -98,7 +98,7 @@ public open class FunctionalExpressionRing>( super.binaryOperationFunction(operation) } -public open class FunctionalExpressionField>( +public open class FunctionalExpressionField>( algebra: A, ) : FunctionalExpressionRing(algebra), Field>, ScaleOperations> { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt index 5814ab35c..fe92a711a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt @@ -48,7 +48,7 @@ public class BufferedLinearSpace>( override fun Matrix.dot(other: Matrix): Matrix { require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } return elementAlgebra { - val rows = this@dot.rows.map{it.linearize()} + val rows = this@dot.rows.map { it.linearize() } val columns = other.columns.map { it.linearize() } buildMatrix(rowNum, other.colNum) { i, j -> val r = rows[i] diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index cf8564e08..740ad12eb 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -175,7 +175,7 @@ public interface LinearSpace> { public fun > buffered( algebra: A, bufferFactory: BufferFactory = Buffer.Companion::boxing, - ): LinearSpace = BufferedLinearSpace(algebra,bufferFactory) + ): LinearSpace = BufferedLinearSpace(algebra, bufferFactory) public val real: LinearSpace = buffered(RealField, ::RealBuffer) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt index 7f0451946..8efa08f81 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt @@ -10,7 +10,7 @@ import space.kscience.kmath.nd.NDStructure public class VirtualMatrix( override val rowNum: Int, override val colNum: Int, - public val generator: (i: Int, j: Int) -> T + public val generator: (i: Int, j: Int) -> T, ) : Matrix { override val shape: IntArray get() = intArrayOf(rowNum, colNum) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt index e3ffae74b..81e1e988a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt @@ -19,7 +19,7 @@ public class ShapeMismatchException(public val expected: IntArray, public val ac * @param C the type of the element context. * @param N the type of the structure. */ -public interface NDAlgebra> { +public interface NDAlgebra> { /** * The shape of ND-structures this algebra operates on. */ @@ -65,11 +65,12 @@ public interface NDAlgebra> { * @param structures the structures to check. * @return the array of valid structures. */ -internal fun > NDAlgebra.checkShape(vararg structures: NDStructure): Array> = structures - .map(NDStructure::shape) - .singleOrNull { !shape.contentEquals(it) } - ?.let>> { throw ShapeMismatchException(shape, it) } - ?: structures +internal fun > NDAlgebra.checkShape(vararg structures: NDStructure): Array> = + structures + .map(NDStructure::shape) + .singleOrNull { !shape.contentEquals(it) } + ?.let>> { throw ShapeMismatchException(shape, it) } + ?: structures /** * Checks if given element is consistent with this context. @@ -77,7 +78,7 @@ internal fun > NDAlgebra.checkShape(vararg structures: ND * @param element the structure to check. * @return the valid structure. */ -internal fun > NDAlgebra.checkShape(element: NDStructure): NDStructure { +internal fun > NDAlgebra.checkShape(element: NDStructure): NDStructure { if (!element.shape.contentEquals(shape)) throw ShapeMismatchException(shape, element.shape) return element } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt index 3e42ac094..b2b5911df 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt @@ -41,7 +41,7 @@ public interface AlgebraElement> { */ @UnstableKMathAPI public operator fun , S : NumbersAddOperations> T.minus(b: T): T = - context.add(this, context.run { -b}) + context.add(this, context.run { -b }) /** * Adds element to this one. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 52a0dec6f..9a395b0f4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -71,7 +71,7 @@ public fun Sequence.sumWith(space: Group): T = space.sum(this) * @return the average value. * @author Iaroslav Postovalov */ -public fun Iterable.averageWith(space: S): T where S : Group, S : ScaleOperations = +public fun Iterable.averageWith(space: S): T where S : Group, S : ScaleOperations = space.average(this) /** @@ -82,7 +82,7 @@ public fun Iterable.averageWith(space: S): T where S : Group, S : * @return the average value. * @author Iaroslav Postovalov */ -public fun Sequence.averageWith(space: S): T where S : Group, S : ScaleOperations = +public fun Sequence.averageWith(space: S): T where S : Group, S : ScaleOperations = space.average(this) //TODO optimized power operation diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt index 0910b2034..c65af7a98 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt @@ -13,10 +13,10 @@ internal class BufferAccessor2D( public val colNum: Int, val factory: MutableBufferFactory, ) { - public operator fun Buffer.get(i: Int, j: Int): T = get(i*colNum + j) + public operator fun Buffer.get(i: Int, j: Int): T = get(i * colNum + j) public operator fun MutableBuffer.set(i: Int, j: Int, value: T) { - set(i*colNum + j, value) + set(i * colNum + j, value) } public inline fun create(crossinline init: (i: Int, j: Int) -> T): MutableBuffer = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt index 9fc7d55f3..5c4ec3b05 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt @@ -38,7 +38,7 @@ public fun FloatBuffer(vararg floats: Float): FloatBuffer = FloatBuffer(floats) /** * Returns a new [FloatArray] containing all of the elements of this [Buffer]. */ -public fun Buffer.toFloatArray(): FloatArray = when(this) { +public fun Buffer.toFloatArray(): FloatArray = when (this) { is FloatBuffer -> array.copyOf() else -> FloatArray(size, ::get) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt index d3d0f79a5..32dfcf9aa 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt @@ -37,7 +37,7 @@ public fun IntBuffer(vararg ints: Int): IntBuffer = IntBuffer(ints) /** * Returns a new [IntArray] containing all of the elements of this [Buffer]. */ -public fun Buffer.toIntArray(): IntArray = when(this) { +public fun Buffer.toIntArray(): IntArray = when (this) { is IntBuffer -> array.copyOf() else -> IntArray(size, ::get) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt index fec358421..48b1d7a7b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt @@ -37,7 +37,7 @@ public fun LongBuffer(vararg longs: Long): LongBuffer = LongBuffer(longs) /** * Returns a new [LongArray] containing all of the elements of this [Buffer]. */ -public fun Buffer.toLongArray(): LongArray = when(this) { +public fun Buffer.toLongArray(): LongArray = when (this) { is LongBuffer -> array.copyOf() else -> LongArray(size, ::get) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt index 418adb537..50a2db590 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt @@ -24,7 +24,7 @@ public open class MemoryBuffer(protected val memory: Memory, protected public inline fun create( spec: MemorySpec, size: Int, - initializer: (Int) -> T + initializer: (Int) -> T, ): MemoryBuffer = MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer -> (0 until size).forEach { buffer[it] = initializer(it) } } @@ -53,7 +53,7 @@ public class MutableMemoryBuffer(memory: Memory, spec: MemorySpec) : public inline fun create( spec: MemorySpec, size: Int, - initializer: (Int) -> T + initializer: (Int) -> T, ): MutableMemoryBuffer = MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer -> (0 until size).forEach { buffer[it] = initializer(it) } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt index 01b533138..b56c03b76 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt @@ -42,7 +42,7 @@ public fun RealBuffer.contentEquals(vararg doubles: Double): Boolean = array.con /** * Returns a new [DoubleArray] containing all of the elements of this [Buffer]. */ -public fun Buffer.toDoubleArray(): DoubleArray = when(this) { +public fun Buffer.toDoubleArray(): DoubleArray = when (this) { is RealBuffer -> array.copyOf() else -> DoubleArray(size, ::get) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt index 77f128403..7832bb863 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt @@ -35,7 +35,7 @@ public fun ShortBuffer(vararg shorts: Short): ShortBuffer = ShortBuffer(shorts) /** * Returns a new [ShortArray] containing all of the elements of this [Buffer]. */ -public fun Buffer.toShortArray(): ShortArray = when(this) { +public fun Buffer.toShortArray(): ShortArray = when (this) { is ShortBuffer -> array.copyOf() else -> ShortArray(size, ::get) } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt index fb90b5e11..e6efc6a8a 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt @@ -17,7 +17,7 @@ class RealLUSolverTest { @Test fun testDecomposition() { LinearSpace.real.run { - val matrix = matrix(2,2)( + val matrix = matrix(2, 2)( 3.0, 1.0, 2.0, 3.0 ) @@ -33,14 +33,14 @@ class RealLUSolverTest { @Test fun testInvert() { - val matrix = LinearSpace.real.matrix(2,2)( + val matrix = LinearSpace.real.matrix(2, 2)( 3.0, 1.0, 1.0, 3.0 ) val inverted = LinearSpace.real.inverseWithLup(matrix) - val expected = LinearSpace.real.matrix(2,2)( + val expected = LinearSpace.real.matrix(2, 2)( 0.375, -0.125, -0.125, 0.375 ) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt index dd7871f9a..e9e6e92fb 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt @@ -11,7 +11,7 @@ import kotlin.test.assertEquals @Suppress("UNUSED_VARIABLE") class NumberNDFieldTest { - val algebra = NDAlgebra.real(3,3) + val algebra = NDAlgebra.real(3, 3) val array1 = algebra.produce { (i, j) -> (i + j).toDouble() } val array2 = algebra.produce { (i, j) -> (i - j).toDouble() } From 2d2c5aa6840902db6c5688d19e2960b124b5e0d3 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Mon, 15 Mar 2021 15:18:21 +0300 Subject: [PATCH 081/393] matrixhelper --- .../kscience/kmath/tensors/BufferedTensor.kt | 53 ++++++++ .../tensors/RealLinearOpsTensorAlgebra.kt | 116 ++++++++++-------- 2 files changed, 120 insertions(+), 49 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index 29605024d..4d89996a0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -13,6 +13,7 @@ public open class BufferedTensor( TensorStrides(shape), buffer ) { + /* public operator fun get(i: Int, j: Int): T { check(this.dimension == 2) { "Not matrix" } @@ -24,8 +25,60 @@ public open class BufferedTensor( this[intArrayOf(i, j)] = value } + */ } +//todo make generator mb nextMatrixIndex? +public class InnerMatrix(private val tensor: BufferedTensor){ + private var offset: Int = 0 + private val n : Int = tensor.shape.size + //stride? + private val step = tensor.shape[n - 1] * tensor.shape[n - 2] + + public operator fun get(i: Int, j: Int): T { + val index = tensor.strides.index(offset) + index[n - 2] = i + index[n - 1] = j + return tensor[index] + } + + public operator fun set(i: Int, j: Int, value: T): Unit { + val index = tensor.strides.index(offset) + index[n - 2] = i + index[n - 1] = j + tensor[index] = value + } + + public fun makeStep(){ + offset += step + } +} + +public class InnerVector(private val tensor: BufferedTensor){ + private var offset: Int = 0 + private val n : Int = tensor.shape.size + //stride? + private val step = tensor.shape[n - 1] + + public operator fun get(i: Int): T { + val index = tensor.strides.index(offset) + index[n - 1] = i + return tensor[index] + } + + public operator fun set(i: Int, value: T): Unit { + val index = tensor.strides.index(offset) + index[n - 1] = i + tensor[index] = value + } + + public fun makeStep(){ + offset += step + } +} + + +//todo default buffer = arrayOf(0)??? public class IntTensor( shape: IntArray, buffer: IntArray diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt index dcd740356..ab39fc6ac 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt @@ -2,8 +2,7 @@ package space.kscience.kmath.tensors public class RealLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, - RealTensorAlgebra() -{ + RealTensorAlgebra() { override fun eye(n: Int): RealTensor { val shape = intArrayOf(n, n) val buffer = DoubleArray(n * n) { 0.0 } @@ -26,55 +25,71 @@ public class RealLinearOpsTensorAlgebra : override fun RealTensor.lu(): Pair { // todo checks - val lu = this.copy() - val m = this.shape[0] - val pivot = IntArray(m) - - - // Initialize permutation array and parity - for (row in 0 until m) pivot[row] = row - var even = true - - for (i in 0 until m) { - var maxA = -1.0 - var iMax = i - - for (k in i until m) { - val absA = kotlin.math.abs(lu[k, i]) - if (absA > maxA) { - maxA = absA - iMax = k - } - } - - //todo check singularity - - if (iMax != i) { - - val j = pivot[i] - pivot[i] = pivot[iMax] - pivot[iMax] = j - even != even - - for (k in 0 until m) { - val tmp = lu[i, k] - lu[i, k] = lu[iMax, k] - lu[iMax, k] = tmp - } - - } - - for (j in i + 1 until m) { - lu[j, i] /= lu[i, i] - for (k in i + 1 until m) { - lu[j, k] -= lu[j, i] * lu[i, k] - } - } + val luTensor = this.copy() + val lu = InnerMatrix(luTensor) + //stride TODO!!! move to generator? + var matCnt = 1 + for (i in 0 until this.shape.size - 2) { + matCnt *= this.shape[i] } - return Pair(lu, IntTensor(intArrayOf(m), pivot)) + val n = this.shape.size + val m = this.shape[n - 1] + val pivotsShape = IntArray(n - 1) { i -> + this.shape[i] + } + val pivotsTensor = IntTensor( + pivotsShape, + IntArray(matCnt * m) { 0 } + ) + val pivot = InnerVector(pivotsTensor) + for (i in 0 until matCnt) { + for (row in 0 until m) pivot[row] = row + + for (i in 0 until m) { + var maxA = -1.0 + var iMax = i + + for (k in i until m) { + val absA = kotlin.math.abs(lu[k, i]) + if (absA > maxA) { + maxA = absA + iMax = k + } + } + + //todo check singularity + + if (iMax != i) { + + val j = pivot[i] + pivot[i] = pivot[iMax] + pivot[iMax] = j + + for (k in 0 until m) { + val tmp = lu[i, k] + lu[i, k] = lu[iMax, k] + lu[iMax, k] = tmp + } + + } + + for (j in i + 1 until m) { + lu[j, i] /= lu[i, i] + for (k in i + 1 until m) { + lu[j, k] -= lu[j, i] * lu[i, k] + } + } + } + lu.makeStep() + pivot.makeStep() + } + + return Pair(luTensor, pivotsTensor) } override fun luPivot(lu: RealTensor, pivots: IntTensor): Triple { + TODO() + /* // todo checks val n = lu.shape[0] val p = lu.zeroesLike() @@ -97,9 +112,12 @@ public class RealLinearOpsTensorAlgebra : } } } - return Triple(p, l, u) + + return Triple(p, l, u)*/ } + + override fun RealTensor.det(): RealTensor { TODO("Not yet implemented") } @@ -127,5 +145,5 @@ public class RealLinearOpsTensorAlgebra : } -public inline fun RealLinearOpsTensorAlgebra(block: RealTensorAlgebra.() -> R): R = +public inline fun RealLinearOpsTensorAlgebra(block: RealLinearOpsTensorAlgebra.() -> R): R = RealLinearOpsTensorAlgebra().block() \ No newline at end of file From 50ed7ce28bb072f33a3527879fe8d9453cba6ac4 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 12:54:46 +0000 Subject: [PATCH 082/393] ComplexTensorAlgebra interface --- .../kmath/tensors/ComplexTensorAlgebra.kt | 47 +++++++++++++++++++ .../kmath/tensors/ComplexTensorStructure.kt | 14 ++++++ .../tensors/RealAnalyticTensorAlgebra.kt | 2 +- .../tensors/RealLinearOpsTensorAlgebra.kt | 2 +- 4 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt new file mode 100644 index 000000000..3f5b7d667 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt @@ -0,0 +1,47 @@ +package space.kscience.kmath.tensors + +public interface ComplexTensorAlgebra, + ComplexTensorType : ComplexTensorStructure> + : TensorPartialDivisionAlgebra{ + + //https://pytorch.org/docs/stable/generated/torch.view_as_complex.html + public fun RealTensorType.viewAsComplex(): ComplexTensorType + + //https://pytorch.org/docs/stable/generated/torch.angle.html + public fun ComplexTensorType.angle(): RealTensorType + + //https://pytorch.org/docs/stable/generated/torch.stft.html#torch.stft + public fun ComplexTensorType.stft( + nFFT: Int, + hopLength: Int, + winLength: Int, + window: RealTensorType, + normalised: Boolean, + oneSided: Boolean + ) + + //https://pytorch.org/docs/stable/generated/torch.istft.html#torch.istft + public fun ComplexTensorType.istft( + nFFT: Int, + hopLength: Int, + winLength: Int, + window: RealTensorType, + center: Boolean, + normalised: Boolean, + oneSided: Boolean, + length: Int + ) + + //https://pytorch.org/docs/stable/generated/torch.bartlett_window.html#torch.bartlett_window + public fun bartlettWindow(windowLength: Int, periodic: Boolean): RealTensorType + + //https://pytorch.org/docs/stable/generated/torch.blackman_window.html#torch.blackman_window + public fun blackmanWindow(windowLength: Int, periodic: Boolean): RealTensorType + + //https://pytorch.org/docs/stable/generated/torch.hamming_window.html#torch.hamming_window + public fun hammingWindow(windowLength: Int, periodic: Boolean, alpha: T, beta: T): RealTensorType + + //https://pytorch.org/docs/stable/generated/torch.kaiser_window.html#torch.kaiser_window + public fun kaiserWindow(windowLength: Int, periodic: Boolean, beta: T): RealTensorType +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt new file mode 100644 index 000000000..0e0975830 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt @@ -0,0 +1,14 @@ +package space.kscience.kmath.tensors + +public interface ComplexTensorStructure> : TensorStructure { + + //https://pytorch.org/docs/master/generated/torch.view_as_real.html + public fun viewAsReal(): RealTensorType + + //https://pytorch.org/docs/stable/generated/torch.real.html + public fun realPart(): RealTensorType + + //https://pytorch.org/docs/stable/generated/torch.imag.html + public fun imaginaryPart(): RealTensorType + +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt index a93ebcb89..f610361fc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt @@ -146,5 +146,5 @@ public class RealAnalyticTensorAlgebra: } -public inline fun RealAnalyticTensorAlgebra(block: RealTensorAlgebra.() -> R): R = +public inline fun RealAnalyticTensorAlgebra(block: RealAnalyticTensorAlgebra.() -> R): R = RealAnalyticTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt index dcd740356..6b1957b8c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt @@ -127,5 +127,5 @@ public class RealLinearOpsTensorAlgebra : } -public inline fun RealLinearOpsTensorAlgebra(block: RealTensorAlgebra.() -> R): R = +public inline fun RealLinearOpsTensorAlgebra(block: RealLinearOpsTensorAlgebra.() -> R): R = RealLinearOpsTensorAlgebra().block() \ No newline at end of file From a3ca861ebe034fc1a8b08f18c2613df3ef81c785 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 13:05:45 +0000 Subject: [PATCH 083/393] Rename FFTs --- .../space/kscience/kmath/tensors/ComplexTensorAlgebra.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt index 3f5b7d667..8399511a5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt @@ -12,7 +12,7 @@ public interface ComplexTensorAlgebra Date: Mon, 15 Mar 2021 16:46:12 +0300 Subject: [PATCH 084/393] Move features to scopes --- .../kscience/kmath/commons/linear/CMMatrix.kt | 82 ++++++++++--------- .../kscience/kmath/linear/LinearSpace.kt | 21 ++--- .../space/kscience/kmath/nd/NDAlgebra.kt | 25 ++++++ .../kscience/kmath/ejml/EjmlLinearSpace.kt | 74 +++++++++++++++++ .../space/kscience/kmath/ejml/EjmlMatrix.kt | 69 +--------------- .../kscience/kmath/ejml/EjmlMatrixTest.kt | 9 +- 6 files changed, 156 insertions(+), 124 deletions(-) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index 5f632491c..5b45c2e51 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -13,44 +13,6 @@ public class CMMatrix(public val origin: RealMatrix) : Matrix { public override val rowNum: Int get() = origin.rowDimension public override val colNum: Int get() = origin.columnDimension - @UnstableKMathAPI - override fun getFeature(type: KClass): T? = when (type) { - DiagonalFeature::class -> if (origin is DiagonalMatrix) DiagonalFeature else null - - DeterminantFeature::class, LupDecompositionFeature::class -> object : - DeterminantFeature, - LupDecompositionFeature { - private val lup by lazy { LUDecomposition(origin) } - override val determinant: Double by lazy { lup.determinant } - override val l: Matrix by lazy { CMMatrix(lup.l) + LFeature } - override val u: Matrix by lazy { CMMatrix(lup.u) + UFeature } - override val p: Matrix by lazy { CMMatrix(lup.p) } - } - - CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { - override val l: Matrix by lazy { - val cholesky = CholeskyDecomposition(origin) - CMMatrix(cholesky.l) + LFeature - } - } - - QRDecompositionFeature::class -> object : QRDecompositionFeature { - private val qr by lazy { QRDecomposition(origin) } - override val q: Matrix by lazy { CMMatrix(qr.q) + OrthogonalFeature } - override val r: Matrix by lazy { CMMatrix(qr.r) + UFeature } - } - - SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { - private val sv by lazy { SingularValueDecomposition(origin) } - override val u: Matrix by lazy { CMMatrix(sv.u) } - override val s: Matrix by lazy { CMMatrix(sv.s) } - override val v: Matrix by lazy { CMMatrix(sv.v) } - override val singularValues: Point by lazy { RealBuffer(sv.singularValues) } - } - - else -> null - }?.let(type::cast) - public override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j) override fun equals(other: Any?): Boolean { @@ -134,6 +96,50 @@ public object CMLinearSpace : LinearSpace { override fun Double.times(v: Point): CMVector = v * this + + @UnstableKMathAPI + override fun getFeature(structure: Matrix, type: KClass): F? { + //Return the feature if it is intrinsic to the structure + structure.getFeature(type)?.let { return it } + + val origin = structure.toCM().origin + + return when (type) { + DiagonalFeature::class -> if (origin is DiagonalMatrix) DiagonalFeature else null + + DeterminantFeature::class, LupDecompositionFeature::class -> object : + DeterminantFeature, + LupDecompositionFeature { + private val lup by lazy { LUDecomposition(origin) } + override val determinant: Double by lazy { lup.determinant } + override val l: Matrix by lazy { CMMatrix(lup.l) + LFeature } + override val u: Matrix by lazy { CMMatrix(lup.u) + UFeature } + override val p: Matrix by lazy { CMMatrix(lup.p) } + } + + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { + override val l: Matrix by lazy { + val cholesky = CholeskyDecomposition(origin) + CMMatrix(cholesky.l) + LFeature + } + } + + QRDecompositionFeature::class -> object : QRDecompositionFeature { + private val qr by lazy { QRDecomposition(origin) } + override val q: Matrix by lazy { CMMatrix(qr.q) + OrthogonalFeature } + override val r: Matrix by lazy { CMMatrix(qr.r) + UFeature } + } + + SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { + private val sv by lazy { SingularValueDecomposition(origin) } + override val u: Matrix by lazy { CMMatrix(sv.u) } + override val s: Matrix by lazy { CMMatrix(sv.s) } + override val v: Matrix by lazy { CMMatrix(sv.v) } + override val singularValues: Point by lazy { RealBuffer(sv.singularValues) } + } + else -> null + }?.let(type::cast) + } } public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 740ad12eb..e8c7d119b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -156,16 +156,15 @@ public interface LinearSpace> { public operator fun T.times(v: Point): Point = v * this /** - * Gets a feature from the matrix. This function may return some additional features to - * [space.kscience.kmath.nd.NDStructure.getFeature]. + * Get a feature of the structure in this scope. Structure features take precedence other context features * * @param F the type of feature. - * @param m the matrix. + * @param structure the structure. * @param type the [KClass] instance of [F]. * @return a feature object or `null` if it isn't present. */ @UnstableKMathAPI - public fun getFeature(m: Matrix, type: KClass): F? = m.getFeature(type) + public fun getFeature(structure: Matrix, type: KClass): F? = structure.getFeature(type) public companion object { @@ -187,19 +186,17 @@ public interface LinearSpace> { } } -public operator fun , R> LS.invoke(block: LS.() -> R): R = run(block) - /** - * Gets a feature from the matrix. This function may return some additional features to - * [space.kscience.kmath.nd.NDStructure.getFeature]. + * Get a feature of the structure in this scope. Structure features take precedence other context features * * @param T the type of items in the matrices. - * @param M the type of operated matrices. * @param F the type of feature. - * @receiver the [LinearSpace] of [T]. - * @param m the matrix. * @return a feature object or `null` if it isn't present. */ @UnstableKMathAPI -public inline fun LinearSpace.getFeature(m: Matrix): F? = getFeature(m, F::class) +public inline fun LinearSpace.getFeature(structure: Matrix): F? = + getFeature(structure, F::class) + + +public operator fun , R> LS.invoke(block: LS.() -> R): R = run(block) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt index 81e1e988a..5514a8f0f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt @@ -1,7 +1,9 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import space.kscience.kmath.structures.* +import kotlin.reflect.KClass /** * An exception is thrown when the expected ans actual shape of NDArray differs. @@ -56,9 +58,32 @@ public interface NDAlgebra> { public operator fun Function1.invoke(structure: NDStructure): NDStructure = structure.map { value -> this@invoke(value) } + /** + * Get a feature of the structure in this scope. Structure features take precedence other context features + * + * @param F the type of feature. + * @param structure the structure. + * @param type the [KClass] instance of [F]. + * @return a feature object or `null` if it isn't present. + */ + @UnstableKMathAPI + public fun getFeature(structure: NDStructure, type: KClass): F? = structure.getFeature(type) + public companion object } + +/** + * Get a feature of the structure in this scope. Structure features take precedence other context features + * + * @param T the type of items in the matrices. + * @param F the type of feature. + * @return a feature object or `null` if it isn't present. + */ +@UnstableKMathAPI +public inline fun NDAlgebra.getFeature(structure: NDStructure): F? = + getFeature(structure, F::class) + /** * Checks if given elements are consistent with this context. * diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index eecd88681..452280295 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -1,10 +1,14 @@ package space.kscience.kmath.ejml +import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.getFeature import space.kscience.kmath.operations.RealField +import space.kscience.kmath.structures.RealBuffer +import kotlin.reflect.KClass +import kotlin.reflect.cast /** * Represents context of basic operations operating with [EjmlMatrix]. @@ -83,6 +87,76 @@ public object EjmlLinearSpace : LinearSpace { override fun Double.times(v: Point): EjmlVector = v.toEjml().origin.scale(this).wrapVector() + + @UnstableKMathAPI + override fun getFeature(structure: Matrix, type: KClass): F? { + //Return the feature if it is intrinsic to the structure + structure.getFeature(type)?.let { return it } + + val origin = structure.toEjml().origin + + return when (type) { + InverseMatrixFeature::class -> object : InverseMatrixFeature { + override val inverse: Matrix by lazy { EjmlMatrix(origin.invert()) } + } + + DeterminantFeature::class -> object : DeterminantFeature { + override val determinant: Double by lazy(origin::determinant) + } + + SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { + private val svd by lazy { + DecompositionFactory_DDRM.svd(origin.numRows(), origin.numCols(), true, true, false) + .apply { decompose(origin.ddrm.copy()) } + } + + override val u: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getU(null, false))) } + override val s: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getW(null))) } + override val v: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getV(null, false))) } + override val singularValues: Point by lazy { RealBuffer(svd.singularValues) } + } + + QRDecompositionFeature::class -> object : QRDecompositionFeature { + private val qr by lazy { + DecompositionFactory_DDRM.qr().apply { decompose(origin.ddrm.copy()) } + } + + override val q: Matrix by lazy { + EjmlMatrix(SimpleMatrix(qr.getQ(null, false))) + OrthogonalFeature + } + + override val r: Matrix by lazy { EjmlMatrix(SimpleMatrix(qr.getR(null, false))) + UFeature } + } + + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { + override val l: Matrix by lazy { + val cholesky = + DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.ddrm.copy()) } + + EjmlMatrix(SimpleMatrix(cholesky.getT(null))) + LFeature + } + } + + LupDecompositionFeature::class -> object : LupDecompositionFeature { + private val lup by lazy { + DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols()) + .apply { decompose(origin.ddrm.copy()) } + } + + override val l: Matrix by lazy { + EjmlMatrix(SimpleMatrix(lup.getLower(null))) + LFeature + } + + override val u: Matrix by lazy { + EjmlMatrix(SimpleMatrix(lup.getUpper(null))) + UFeature + } + + override val p: Matrix by lazy { EjmlMatrix(SimpleMatrix(lup.getRowPivot(null))) } + } + + else -> null + }?.let(type::cast) + } } /** diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index a1984fa31..5f93af729 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -1,13 +1,8 @@ package space.kscience.kmath.ejml -import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.simple.SimpleMatrix -import space.kscience.kmath.linear.* -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.linear.Matrix import space.kscience.kmath.nd.NDStructure -import space.kscience.kmath.structures.RealBuffer -import kotlin.reflect.KClass -import kotlin.reflect.cast /** * Represents featured matrix over EJML [SimpleMatrix]. @@ -19,68 +14,6 @@ public class EjmlMatrix(public val origin: SimpleMatrix) : Matrix { public override val rowNum: Int get() = origin.numRows() public override val colNum: Int get() = origin.numCols() - @UnstableKMathAPI - public override fun getFeature(type: KClass): T? = when (type) { - InverseMatrixFeature::class -> object : InverseMatrixFeature { - override val inverse: Matrix by lazy { EjmlMatrix(origin.invert()) } - } - - DeterminantFeature::class -> object : DeterminantFeature { - override val determinant: Double by lazy(origin::determinant) - } - - SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { - private val svd by lazy { - DecompositionFactory_DDRM.svd(origin.numRows(), origin.numCols(), true, true, false) - .apply { decompose(origin.ddrm.copy()) } - } - - override val u: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getU(null, false))) } - override val s: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getW(null))) } - override val v: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getV(null, false))) } - override val singularValues: Point by lazy { RealBuffer(svd.singularValues) } - } - - QRDecompositionFeature::class -> object : QRDecompositionFeature { - private val qr by lazy { - DecompositionFactory_DDRM.qr().apply { decompose(origin.ddrm.copy()) } - } - - override val q: Matrix by lazy { - EjmlMatrix(SimpleMatrix(qr.getQ(null, false))) + OrthogonalFeature - } - - override val r: Matrix by lazy { EjmlMatrix(SimpleMatrix(qr.getR(null, false))) + UFeature } - } - - CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { - override val l: Matrix by lazy { - val cholesky = - DecompositionFactory_DDRM.chol(rowNum, true).apply { decompose(origin.ddrm.copy()) } - - EjmlMatrix(SimpleMatrix(cholesky.getT(null))) + LFeature - } - } - - LupDecompositionFeature::class -> object : LupDecompositionFeature { - private val lup by lazy { - DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols()).apply { decompose(origin.ddrm.copy()) } - } - - override val l: Matrix by lazy { - EjmlMatrix(SimpleMatrix(lup.getLower(null))) + LFeature - } - - override val u: Matrix by lazy { - EjmlMatrix(SimpleMatrix(lup.getUpper(null))) + UFeature - } - - override val p: Matrix by lazy { EjmlMatrix(SimpleMatrix(lup.getRowPivot(null))) } - } - - else -> null - }?.let(type::cast) - public override operator fun get(i: Int, j: Int): Double = origin[i, j] override fun equals(other: Any?): Boolean { diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt index 7f31d2f93..70b2ce723 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -2,10 +2,7 @@ package space.kscience.kmath.ejml import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.simple.SimpleMatrix -import space.kscience.kmath.linear.DeterminantFeature -import space.kscience.kmath.linear.LupDecompositionFeature -import space.kscience.kmath.linear.MatrixFeature -import space.kscience.kmath.linear.plus +import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.getFeature import kotlin.random.Random @@ -45,9 +42,9 @@ internal class EjmlMatrixTest { fun features() { val m = randomMatrix val w = EjmlMatrix(m) - val det = w.getFeature>() ?: fail() + val det: DeterminantFeature = EjmlLinearSpace.getFeature(w) ?: fail() assertEquals(m.determinant(), det.determinant) - val lup = w.getFeature>() ?: fail() + val lup: LupDecompositionFeature = EjmlLinearSpace.getFeature(w) ?: fail() val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows(), m.numCols()) .also { it.decompose(m.ddrm.copy()) } From cceffa09e827bf0e17a2d79784d8927ce5653f6b Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 15 Mar 2021 19:24:07 +0300 Subject: [PATCH 085/393] Bump dev version --- build.gradle.kts | 2 +- .../space/kscience/kmath/commons/linear/CMMatrix.kt | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 113107f69..9810e378f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,7 +20,7 @@ allprojects { } group = "space.kscience" - version = "0.3.0" + version = "0.3.0-dev-2" } subprojects { diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index 5b45c2e51..4671598f7 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -103,7 +103,7 @@ public object CMLinearSpace : LinearSpace { structure.getFeature(type)?.let { return it } val origin = structure.toCM().origin - + return when (type) { DiagonalFeature::class -> if (origin is DiagonalMatrix) DiagonalFeature else null @@ -142,11 +142,8 @@ public object CMLinearSpace : LinearSpace { } } -public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix = - CMMatrix(origin.add(other.origin)) +public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix = CMMatrix(origin.add(other.origin)) -public operator fun CMMatrix.minus(other: CMMatrix): CMMatrix = - CMMatrix(origin.subtract(other.origin)) +public operator fun CMMatrix.minus(other: CMMatrix): CMMatrix = CMMatrix(origin.subtract(other.origin)) -public infix fun CMMatrix.dot(other: CMMatrix): CMMatrix = - CMMatrix(origin.multiply(other.origin)) +public infix fun CMMatrix.dot(other: CMMatrix): CMMatrix = CMMatrix(origin.multiply(other.origin)) From 913c12fb3002f7b218036e5cc42d8f82ba1a518c Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 15 Mar 2021 19:39:22 +0300 Subject: [PATCH 086/393] fix coordinates --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6f2675425..0e874ac31 100644 --- a/README.md +++ b/README.md @@ -253,8 +253,8 @@ repositories { } dependencies { - api("kscience.kmath:kmath-core:0.2.0") - // api("kscience.kmath:kmath-core-jvm:0.2.0") for jvm-specific version + api("space.kscience.kmath:kmath-core:0.2.1") + // api("space.kscience.kmath:kmath-core-jvm:0.2.1") for jvm-specific version } ``` From 179a07e03432f4ded4e151ac384e8630705ee546 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 15 Mar 2021 19:41:37 +0300 Subject: [PATCH 087/393] Bump readme --- README.md | 7 ++++--- docs/templates/README-TEMPLATE.md | 4 +--- kmath-ast/README.md | 6 +++--- kmath-complex/README.md | 6 +++--- kmath-for-real/README.md | 6 +++--- kmath-functions/README.md | 6 +++--- kmath-nd4j/README.md | 6 +++--- 7 files changed, 20 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index c95b0a13f..c129ba4ba 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ [![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) + ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) -[![Kotlin JS IR supported](https://img.shields.io/badge/Kotlin%2FJS-IR%20supported-yellow)](https://kotl.in/jsirsupported) +[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22%20AND%20a:%22kmath-core%22) # KMath @@ -253,8 +254,8 @@ repositories { } dependencies { - api("kscience.kmath:kmath-core:() -> kotlin.Any") - // api("kscience.kmath:kmath-core-jvm:() -> kotlin.Any") for jvm-specific version + api("kscience.kmath:kmath-core:0.3.0-dev-2") + // api("kscience.kmath:kmath-core-jvm:0.3.0-dev-2") for jvm-specific version } ``` diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index 10bc7aab1..c8be0d300 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -3,9 +3,7 @@ ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) -Bintray: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) - -Bintray-dev: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion) +[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22%20AND%20a:%22kmath-core%22) # KMath diff --git a/kmath-ast/README.md b/kmath-ast/README.md index e52f0fa96..a88b6f696 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -12,7 +12,7 @@ This subproject implements the following features: > #### Artifact: > -> This module artifact: `space.kscience:kmath-ast:0.2.0`. +> This module artifact: `space.kscience:kmath-ast:0.3.0-dev-2`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-ast/_latestVersion) > @@ -31,7 +31,7 @@ This subproject implements the following features: > } > > dependencies { -> implementation 'space.kscience:kmath-ast:0.2.0' +> implementation 'space.kscience:kmath-ast:0.3.0-dev-2' > } > ``` > **Gradle Kotlin DSL:** @@ -47,7 +47,7 @@ This subproject implements the following features: > } > > dependencies { -> implementation("space.kscience:kmath-ast:0.2.0") +> implementation("space.kscience:kmath-ast:0.3.0-dev-2") > } > ``` diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 71a75bd3e..7a7628a2c 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath: > #### Artifact: > -> This module artifact: `space.kscience:kmath-complex:0.2.0`. +> This module artifact: `space.kscience:kmath-complex:0.3.0-dev-2`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-complex/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-complex/_latestVersion) > @@ -27,7 +27,7 @@ Complex and hypercomplex number systems in KMath: > } > > dependencies { -> implementation 'space.kscience:kmath-complex:0.2.0' +> implementation 'space.kscience:kmath-complex:0.3.0-dev-2' > } > ``` > **Gradle Kotlin DSL:** @@ -43,6 +43,6 @@ Complex and hypercomplex number systems in KMath: > } > > dependencies { -> implementation("space.kscience:kmath-complex:0.2.0") +> implementation("space.kscience:kmath-complex:0.3.0-dev-2") > } > ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 94b9eb59a..63c5cd249 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -7,7 +7,7 @@ > #### Artifact: > -> This module artifact: `space.kscience:kmath-for-real:0.2.0`. +> This module artifact: `space.kscience:kmath-for-real:0.3.0-dev-2`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-for-real/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-for-real/_latestVersion) > @@ -26,7 +26,7 @@ > } > > dependencies { -> implementation 'space.kscience:kmath-for-real:0.2.0' +> implementation 'space.kscience:kmath-for-real:0.3.0-dev-2' > } > ``` > **Gradle Kotlin DSL:** @@ -42,6 +42,6 @@ > } > > dependencies { -> implementation("space.kscience:kmath-for-real:0.2.0") +> implementation("space.kscience:kmath-for-real:0.3.0-dev-2") > } > ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 0eae4e3c0..29cc68c8e 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -10,7 +10,7 @@ Functions and interpolations: > #### Artifact: > -> This module artifact: `space.kscience:kmath-functions:0.2.0`. +> This module artifact: `space.kscience:kmath-functions:0.3.0-dev-2`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-functions/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-functions/_latestVersion) > @@ -29,7 +29,7 @@ Functions and interpolations: > } > > dependencies { -> implementation 'space.kscience:kmath-functions:0.2.0' +> implementation 'space.kscience:kmath-functions:0.3.0-dev-2' > } > ``` > **Gradle Kotlin DSL:** @@ -45,6 +45,6 @@ Functions and interpolations: > } > > dependencies { -> implementation("space.kscience:kmath-functions:0.2.0") +> implementation("space.kscience:kmath-functions:0.3.0-dev-2") > } > ``` diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 046c8127f..08f0ae541 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ This subproject implements the following features: > #### Artifact: > -> This module artifact: `space.kscience:kmath-nd4j:0.2.0`. +> This module artifact: `space.kscience:kmath-nd4j:0.3.0-dev-2`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-nd4j/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-nd4j/_latestVersion) > @@ -28,7 +28,7 @@ This subproject implements the following features: > } > > dependencies { -> implementation 'space.kscience:kmath-nd4j:0.2.0' +> implementation 'space.kscience:kmath-nd4j:0.3.0-dev-2' > } > ``` > **Gradle Kotlin DSL:** @@ -44,7 +44,7 @@ This subproject implements the following features: > } > > dependencies { -> implementation("space.kscience:kmath-nd4j:0.2.0") +> implementation("space.kscience:kmath-nd4j:0.3.0-dev-2") > } > ``` From 17647742a8a5f1c7d99bf88b6905210ac7e75922 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 15 Mar 2021 19:45:46 +0300 Subject: [PATCH 088/393] Bump readme --- kmath-core/README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 kmath-core/README.md diff --git a/kmath-core/README.md b/kmath-core/README.md new file mode 100644 index 000000000..14f1ecb41 --- /dev/null +++ b/kmath-core/README.md @@ -0,0 +1,55 @@ +# The Core Module (`kmath-core`) + +The core features of KMath: + + - [algebras](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields. + - [nd](src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures and operations on them. + - [linear](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition. + - [buffers](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure + - [expressions](src/commonMain/kotlin/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of +objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high +performance calculations to code generation. + - [domains](src/commonMain/kotlin/kscience/kmath/domains) : Domains + - [autodif](src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation + + +> #### Artifact: +> +> This module artifact: `space.kscience:kmath-core:0.3.0-dev-2`. +> +> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) +> +> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion) +> +> **Gradle:** +> +> ```gradle +> repositories { +> maven { url 'https://repo.kotlin.link' } +> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } +> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap +>// Uncomment if repo.kotlin.link is unavailable +>// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } +>// maven { url 'https://dl.bintray.com/mipt-npm/dev' } +> } +> +> dependencies { +> implementation 'space.kscience:kmath-core:0.3.0-dev-2' +> } +> ``` +> **Gradle Kotlin DSL:** +> +> ```kotlin +> repositories { +> maven("https://repo.kotlin.link") +> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap +> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a +>// Uncomment if repo.kotlin.link is unavailable +>// maven("https://dl.bintray.com/mipt-npm/kscience") +>// maven("https://dl.bintray.com/mipt-npm/dev") +> } +> +> dependencies { +> implementation("space.kscience:kmath-core:0.3.0-dev-2") +> } +> ``` From 484a58755fe2b97c7fa2e8c05fbc0245a102c407 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 15 Mar 2021 19:57:01 +0300 Subject: [PATCH 089/393] Bump readme --- README.md | 2 +- docs/templates/ARTIFACT-TEMPLATE.md | 6 ------ docs/templates/README-TEMPLATE.md | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index c129ba4ba..436495c9c 100644 --- a/README.md +++ b/README.md @@ -254,7 +254,7 @@ repositories { } dependencies { - api("kscience.kmath:kmath-core:0.3.0-dev-2") + api("space.kscience:kmath-core:0.3.0-dev-2") // api("kscience.kmath:kmath-core-jvm:0.3.0-dev-2") for jvm-specific version } ``` diff --git a/docs/templates/ARTIFACT-TEMPLATE.md b/docs/templates/ARTIFACT-TEMPLATE.md index 8ac71193f..cb741bc6f 100644 --- a/docs/templates/ARTIFACT-TEMPLATE.md +++ b/docs/templates/ARTIFACT-TEMPLATE.md @@ -13,9 +13,6 @@ > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { @@ -29,9 +26,6 @@ > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index c8be0d300..4366c8fcd 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -104,7 +104,7 @@ repositories { } dependencies { - api("kscience.kmath:kmath-core:$version") + api("${group}:kmath-core:$version") // api("kscience.kmath:kmath-core-jvm:$version") for jvm-specific version } ``` From f66ac653e0264881d1197a395be84bdb37902b23 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 16:59:50 +0000 Subject: [PATCH 090/393] RealTensor to DoubleTensor rename --- .../kscience/kmath/tensors/BufferedTensor.kt | 2 +- .../tensors/DoubleAnalyticTensorAlgebra.kt | 150 ++++++++++++++++++ ...bra.kt => DoubleLinearOpsTensorAlgebra.kt} | 26 +-- ...ensorAlgebra.kt => DoubleTensorAlgebra.kt} | 128 +++++++-------- .../tensors/RealAnalyticTensorAlgebra.kt | 150 ------------------ .../space/kscience/kmath/tensors/utils.kt | 6 +- .../kscience/kmath/tensors/TestRealTensor.kt | 4 +- .../kmath/tensors/TestRealTensorAlgebra.kt | 20 +-- 8 files changed, 243 insertions(+), 243 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{RealLinearOpsTensorAlgebra.kt => DoubleLinearOpsTensorAlgebra.kt} (73%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{RealTensorAlgebra.kt => DoubleTensorAlgebra.kt} (54%) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index 29605024d..066fb8708 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -41,7 +41,7 @@ public class FloatTensor( buffer: FloatArray ) : BufferedTensor(shape, FloatBuffer(buffer)) -public class RealTensor( +public class DoubleTensor( shape: IntArray, buffer: DoubleArray ) : BufferedTensor(shape, RealBuffer(buffer)) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt new file mode 100644 index 000000000..702049a20 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt @@ -0,0 +1,150 @@ +package space.kscience.kmath.tensors + +public class RealAnalyticTensorAlgebra: + AnalyticTensorAlgebra, + RealTensorAlgebra() +{ + override fun DoubleTensor.exp(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.log(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.sqrt(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.square(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.cos(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.acos(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.cosh(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.acosh(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.sin(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.asin(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.sinh(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.asinh(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.tan(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.atan(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.tanh(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.atanh(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.ceil(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.floor(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.clamp(min: Double, max: Double): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.erf(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.erfinv(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.erfc(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.lerp(end: DoubleTensor, weight: DoubleTensor): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.lgamma(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.logit(eps: Double): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.igamma(other: DoubleTensor): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.igammac(other: DoubleTensor): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.mvlgamma(dimensions: Int): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.polygamma(order: Int): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.pow(exponent: Double): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.round(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.sigmoid(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.sinc(): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.heaviside(values: DoubleTensor): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.trapz(xValues: DoubleTensor, dim: Int): DoubleTensor { + TODO("Not yet implemented") + } + +} + +public inline fun RealAnalyticTensorAlgebra(block: RealAnalyticTensorAlgebra.() -> R): R = + RealAnalyticTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt similarity index 73% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt index 6b1957b8c..5fd8c4151 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt @@ -1,13 +1,13 @@ package space.kscience.kmath.tensors public class RealLinearOpsTensorAlgebra : - LinearOpsTensorAlgebra, + LinearOpsTensorAlgebra, RealTensorAlgebra() { - override fun eye(n: Int): RealTensor { + override fun eye(n: Int): DoubleTensor { val shape = intArrayOf(n, n) val buffer = DoubleArray(n * n) { 0.0 } - val res = RealTensor(shape, buffer) + val res = DoubleTensor(shape, buffer) for (i in 0 until n) { res[intArrayOf(i, i)] = 1.0 } @@ -15,16 +15,16 @@ public class RealLinearOpsTensorAlgebra : } - override fun RealTensor.dot(other: RealTensor): RealTensor { + override fun DoubleTensor.dot(other: DoubleTensor): DoubleTensor { TODO("Alya") } - override fun diagonalEmbedding(diagonalEntries: RealTensor, offset: Int, dim1: Int, dim2: Int): RealTensor { + override fun diagonalEmbedding(diagonalEntries: DoubleTensor, offset: Int, dim1: Int, dim2: Int): DoubleTensor { TODO("Alya") } - override fun RealTensor.lu(): Pair { + override fun DoubleTensor.lu(): Pair { // todo checks val lu = this.copy() val m = this.shape[0] @@ -74,7 +74,7 @@ public class RealLinearOpsTensorAlgebra : return Pair(lu, IntTensor(intArrayOf(m), pivot)) } - override fun luPivot(lu: RealTensor, pivots: IntTensor): Triple { + override fun luPivot(lu: DoubleTensor, pivots: IntTensor): Triple { // todo checks val n = lu.shape[0] val p = lu.zeroesLike() @@ -100,28 +100,28 @@ public class RealLinearOpsTensorAlgebra : return Triple(p, l, u) } - override fun RealTensor.det(): RealTensor { + override fun DoubleTensor.det(): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.inv(): RealTensor { + override fun DoubleTensor.inv(): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.cholesky(): RealTensor { + override fun DoubleTensor.cholesky(): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.qr(): RealTensor { + override fun DoubleTensor.qr(): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.svd(): Triple { + override fun DoubleTensor.svd(): Triple { TODO("Not yet implemented") } - override fun RealTensor.symEig(eigenvectors: Boolean): Pair { + override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt similarity index 54% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 83a513a7a..dd15a257c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -1,146 +1,146 @@ package space.kscience.kmath.tensors -public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { +public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { - override fun RealTensor.value(): Double { + override fun DoubleTensor.value(): Double { check(this.shape contentEquals intArrayOf(1)) { "Inconsistent value for tensor of shape ${shape.toList()}" } return this.buffer.unsafeToDoubleArray()[0] } - override fun zeros(shape: IntArray): RealTensor { + override fun zeros(shape: IntArray): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.zeroesLike(): RealTensor { + override fun DoubleTensor.zeroesLike(): DoubleTensor { val shape = this.shape val buffer = DoubleArray(this.buffer.size) { 0.0 } - return RealTensor(shape, buffer) + return DoubleTensor(shape, buffer) } - override fun ones(shape: IntArray): RealTensor { + override fun ones(shape: IntArray): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.onesLike(): RealTensor { + override fun DoubleTensor.onesLike(): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.copy(): RealTensor { + override fun DoubleTensor.copy(): DoubleTensor { // should be rework as soon as copy() method for NDBuffer will be available - return RealTensor(this.shape, this.buffer.unsafeToDoubleArray().copyOf()) + return DoubleTensor(this.shape, this.buffer.unsafeToDoubleArray().copyOf()) } - override fun Double.plus(other: RealTensor): RealTensor { + override fun Double.plus(other: DoubleTensor): DoubleTensor { val resBuffer = DoubleArray(other.buffer.size) { i -> other.buffer.unsafeToDoubleArray()[i] + this } - return RealTensor(other.shape, resBuffer) + return DoubleTensor(other.shape, resBuffer) } - override fun RealTensor.plus(value: Double): RealTensor = value + this + override fun DoubleTensor.plus(value: Double): DoubleTensor = value + this - override fun RealTensor.plus(other: RealTensor): RealTensor { + override fun DoubleTensor.plus(other: DoubleTensor): DoubleTensor { val broadcast = broadcastTensors(this, other) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.buffer.size) { i -> newThis.buffer.unsafeToDoubleArray()[i] + newOther.buffer.unsafeToDoubleArray()[i] } - return RealTensor(newThis.shape, resBuffer) + return DoubleTensor(newThis.shape, resBuffer) } - override fun RealTensor.plusAssign(value: Double) { + override fun DoubleTensor.plusAssign(value: Double) { for (i in this.buffer.unsafeToDoubleArray().indices) { this.buffer.unsafeToDoubleArray()[i] += value } } - override fun RealTensor.plusAssign(other: RealTensor) { + override fun DoubleTensor.plusAssign(other: DoubleTensor) { //todo should be change with broadcasting for (i in this.buffer.unsafeToDoubleArray().indices) { this.buffer.unsafeToDoubleArray()[i] += other.buffer.unsafeToDoubleArray()[i] } } - override fun Double.minus(other: RealTensor): RealTensor { + override fun Double.minus(other: DoubleTensor): DoubleTensor { val resBuffer = DoubleArray(other.buffer.size) { i -> this - other.buffer.unsafeToDoubleArray()[i] } - return RealTensor(other.shape, resBuffer) + return DoubleTensor(other.shape, resBuffer) } - override fun RealTensor.minus(value: Double): RealTensor { + override fun DoubleTensor.minus(value: Double): DoubleTensor { val resBuffer = DoubleArray(this.buffer.size) { i -> this.buffer.unsafeToDoubleArray()[i] - value } - return RealTensor(this.shape, resBuffer) + return DoubleTensor(this.shape, resBuffer) } - override fun RealTensor.minus(other: RealTensor): RealTensor { + override fun DoubleTensor.minus(other: DoubleTensor): DoubleTensor { val broadcast = broadcastTensors(this, other) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.buffer.size) { i -> newThis.buffer.unsafeToDoubleArray()[i] - newOther.buffer.unsafeToDoubleArray()[i] } - return RealTensor(newThis.shape, resBuffer) + return DoubleTensor(newThis.shape, resBuffer) } - override fun RealTensor.minusAssign(value: Double) { + override fun DoubleTensor.minusAssign(value: Double) { for (i in this.buffer.unsafeToDoubleArray().indices) { this.buffer.unsafeToDoubleArray()[i] -= value } } - override fun RealTensor.minusAssign(other: RealTensor) { + override fun DoubleTensor.minusAssign(other: DoubleTensor) { TODO("Alya") } - override fun Double.times(other: RealTensor): RealTensor { + override fun Double.times(other: DoubleTensor): DoubleTensor { //todo should be change with broadcasting val resBuffer = DoubleArray(other.buffer.size) { i -> other.buffer.unsafeToDoubleArray()[i] * this } - return RealTensor(other.shape, resBuffer) + return DoubleTensor(other.shape, resBuffer) } //todo should be change with broadcasting - override fun RealTensor.times(value: Double): RealTensor = value * this + override fun DoubleTensor.times(value: Double): DoubleTensor = value * this - override fun RealTensor.times(other: RealTensor): RealTensor { + override fun DoubleTensor.times(other: DoubleTensor): DoubleTensor { //todo should be change with broadcasting val resBuffer = DoubleArray(this.buffer.size) { i -> this.buffer.unsafeToDoubleArray()[i] * other.buffer.unsafeToDoubleArray()[i] } - return RealTensor(this.shape, resBuffer) + return DoubleTensor(this.shape, resBuffer) } - override fun RealTensor.timesAssign(value: Double) { + override fun DoubleTensor.timesAssign(value: Double) { //todo should be change with broadcasting for (i in this.buffer.unsafeToDoubleArray().indices) { this.buffer.unsafeToDoubleArray()[i] *= value } } - override fun RealTensor.timesAssign(other: RealTensor) { + override fun DoubleTensor.timesAssign(other: DoubleTensor) { //todo should be change with broadcasting for (i in this.buffer.unsafeToDoubleArray().indices) { this.buffer.unsafeToDoubleArray()[i] *= other.buffer.unsafeToDoubleArray()[i] } } - override fun RealTensor.unaryMinus(): RealTensor { + override fun DoubleTensor.unaryMinus(): DoubleTensor { val resBuffer = DoubleArray(this.buffer.size) { i -> this.buffer.unsafeToDoubleArray()[i].unaryMinus() } - return RealTensor(this.shape, resBuffer) + return DoubleTensor(this.shape, resBuffer) } - override fun RealTensor.transpose(i: Int, j: Int): RealTensor { + override fun DoubleTensor.transpose(i: Int, j: Int): DoubleTensor { checkTranspose(this.dimension, i, j) val n = this.buffer.size val resBuffer = DoubleArray(n) @@ -148,7 +148,7 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra, dim: Int): RealTensor { + override fun cat(tensors: List, dim: Int): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.div(value: Double): RealTensor { + override fun DoubleTensor.div(value: Double): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.div(other: RealTensor): RealTensor { + override fun DoubleTensor.div(other: DoubleTensor): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.flatten(startDim: Int, endDim: Int): RealTensor { + override fun DoubleTensor.flatten(startDim: Int, endDim: Int): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.divAssign(value: Double) { + override fun DoubleTensor.divAssign(value: Double) { TODO("Not yet implemented") } - override fun RealTensor.divAssign(other: RealTensor) { + override fun DoubleTensor.divAssign(other: DoubleTensor) { TODO("Not yet implemented") } - override fun RealTensor.mean(dim: Int, keepDim: Boolean): RealTensor { + override fun DoubleTensor.mean(dim: Int, keepDim: Boolean): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.quantile(q: Double, dim: Int, keepDim: Boolean): RealTensor { + override fun DoubleTensor.quantile(q: Double, dim: Int, keepDim: Boolean): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.std(dim: Int, unbiased: Boolean, keepDim: Boolean): RealTensor { + override fun DoubleTensor.std(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): RealTensor { + override fun DoubleTensor.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { TODO("Not yet implemented") } - override fun RealTensor.histc(bins: Int, min: Double, max: Double): RealTensor { + override fun DoubleTensor.histc(bins: Int, min: Double, max: Double): DoubleTensor { TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt deleted file mode 100644 index f610361fc..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/RealAnalyticTensorAlgebra.kt +++ /dev/null @@ -1,150 +0,0 @@ -package space.kscience.kmath.tensors - -public class RealAnalyticTensorAlgebra: - AnalyticTensorAlgebra, - RealTensorAlgebra() -{ - override fun RealTensor.exp(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.log(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.sqrt(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.square(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.cos(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.acos(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.cosh(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.acosh(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.sin(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.asin(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.sinh(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.asinh(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.tan(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.atan(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.tanh(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.atanh(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.ceil(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.floor(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.clamp(min: Double, max: Double): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.erf(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.erfinv(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.erfc(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.lerp(end: RealTensor, weight: RealTensor): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.lgamma(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.logit(eps: Double): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.igamma(other: RealTensor): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.igammac(other: RealTensor): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.mvlgamma(dimensions: Int): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.polygamma(order: Int): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.pow(exponent: Double): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.round(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.sigmoid(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.sinc(): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.heaviside(values: RealTensor): RealTensor { - TODO("Not yet implemented") - } - - override fun RealTensor.trapz(xValues: RealTensor, dim: Int): RealTensor { - TODO("Not yet implemented") - } - -} - -public inline fun RealAnalyticTensorAlgebra(block: RealAnalyticTensorAlgebra.() -> R): R = - RealAnalyticTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt index b03fb7dd7..9f7e811db 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt @@ -32,13 +32,13 @@ internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { return totalShape } -internal inline fun broadcastTensors(vararg tensors: RealTensor): List { +internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List { val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) val n = totalShape.reduce { acc, i -> acc * i } - val res = ArrayList(0) + val res = ArrayList(0) for (tensor in tensors) { - val resTensor = RealTensor(totalShape, DoubleArray(n)) + val resTensor = DoubleTensor(totalShape, DoubleArray(n)) for (linearIndex in 0 until n) { val totalMultiIndex = resTensor.strides.index(linearIndex) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt index 473a3da8b..5d42e6d0f 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt @@ -11,13 +11,13 @@ class TestRealTensor { @Test fun valueTest() = RealTensorAlgebra { val value = 12.5 - val tensor = RealTensor(intArrayOf(1), doubleArrayOf(value)) + val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @Test fun stridesTest(){ - val tensor = RealTensor(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) + val tensor = DoubleTensor(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) assertEquals(tensor[intArrayOf(0,1)], 5.8) assertTrue(tensor.elements().map{ it.second }.toList().toDoubleArray() contentEquals tensor.buffer.toDoubleArray()) } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index 72bbf1787..3e27a1cc2 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -8,14 +8,14 @@ class TestRealTensorAlgebra { @Test fun doublePlus() = RealTensorAlgebra { - val tensor = RealTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0)) + val tensor = DoubleTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(11.0,12.0)) } @Test fun transpose1x1() = RealTensorAlgebra { - val tensor = RealTensor(intArrayOf(1), doubleArrayOf(0.0)) + val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(0.0)) val res = tensor.transpose(0, 0) assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(0.0)) @@ -24,7 +24,7 @@ class TestRealTensorAlgebra { @Test fun transpose3x2() = RealTensorAlgebra { - val tensor = RealTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor = DoubleTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) @@ -33,7 +33,7 @@ class TestRealTensorAlgebra { @Test fun transpose1x2x3() = RealTensorAlgebra { - val tensor = RealTensor(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor = DoubleTensor(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transpose(0, 1) val res02 = tensor.transpose(0, 2) val res12 = tensor.transpose(1, 2) @@ -60,9 +60,9 @@ class TestRealTensorAlgebra { @Test fun broadcastTensors() = RealTensorAlgebra { - val tensor1 = RealTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = RealTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) val res = broadcastTensors(tensor1, tensor2, tensor3) @@ -77,9 +77,9 @@ class TestRealTensorAlgebra { @Test fun minusTensor() = RealTensorAlgebra { - val tensor1 = RealTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = RealTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = RealTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) assertTrue((tensor2 - tensor1).shape contentEquals intArrayOf(2, 3)) assertTrue((tensor2 - tensor1).buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) From acfdd187a46caf29ef3a856a0c4966dbde19d42b Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 15 Mar 2021 20:17:04 +0300 Subject: [PATCH 091/393] Bump readme --- README.md | 4 +++- docs/templates/README-TEMPLATE.md | 4 +++- kmath-ast/README.md | 6 ------ kmath-complex/README.md | 6 ------ kmath-core/README.md | 6 ------ kmath-for-real/README.md | 6 ------ kmath-functions/README.md | 6 ------ kmath-nd4j/README.md | 6 ------ 8 files changed, 6 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 436495c9c..bfa5c7fb0 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ Python's NumPy library. Later we found that kotlin is much more flexible languag designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could be achieved with [kmath-for-real](/kmath-for-real) extension module. +[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/) + ## Publications and talks * [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2) @@ -255,7 +257,7 @@ repositories { dependencies { api("space.kscience:kmath-core:0.3.0-dev-2") - // api("kscience.kmath:kmath-core-jvm:0.3.0-dev-2") for jvm-specific version + // api("space.kscience:kmath-core-jvm:0.3.0-dev-2") for jvm-specific version } ``` diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index 4366c8fcd..f0e68f575 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -12,6 +12,8 @@ Python's NumPy library. Later we found that kotlin is much more flexible languag designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could be achieved with [kmath-for-real](/kmath-for-real) extension module. +[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/) + ## Publications and talks * [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2) @@ -105,7 +107,7 @@ repositories { dependencies { api("${group}:kmath-core:$version") - // api("kscience.kmath:kmath-core-jvm:$version") for jvm-specific version + // api("${group}:kmath-core-jvm:$version") for jvm-specific version } ``` diff --git a/kmath-ast/README.md b/kmath-ast/README.md index a88b6f696..529586424 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -25,9 +25,6 @@ This subproject implements the following features: > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { @@ -41,9 +38,6 @@ This subproject implements the following features: > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 7a7628a2c..a6b87b81c 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -21,9 +21,6 @@ Complex and hypercomplex number systems in KMath: > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { @@ -37,9 +34,6 @@ Complex and hypercomplex number systems in KMath: > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { diff --git a/kmath-core/README.md b/kmath-core/README.md index 14f1ecb41..2ec97073e 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -28,9 +28,6 @@ performance calculations to code generation. > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { @@ -44,9 +41,6 @@ performance calculations to code generation. > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 63c5cd249..4cc434787 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -20,9 +20,6 @@ > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { @@ -36,9 +33,6 @@ > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 29cc68c8e..b8aa4dee7 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -23,9 +23,6 @@ Functions and interpolations: > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { @@ -39,9 +36,6 @@ Functions and interpolations: > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 08f0ae541..7e38eb6ab 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -22,9 +22,6 @@ This subproject implements the following features: > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { @@ -38,9 +35,6 @@ This subproject implements the following features: > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { From b227a82a80d406fa3c4b4e50373a02363f161954 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 19:06:33 +0000 Subject: [PATCH 092/393] OrderedTensorAlgebra --- .../kmath/tensors/ComplexTensorAlgebra.kt | 6 +++ .../tensors/DoubleAnalyticTensorAlgebra.kt | 8 +-- .../tensors/DoubleLinearOpsTensorAlgebra.kt | 32 ++---------- .../tensors/DoubleOrderedTensorAlgebra.kt | 41 +++++++++++++++ .../kmath/tensors/DoubleTensorAlgebra.kt | 51 ++++++++----------- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 15 ------ .../kmath/tensors/OrderedTensorAlgebra.kt | 29 +++++++++++ .../kscience/kmath/tensors/TensorAlgebra.kt | 35 +++++-------- .../kscience/kmath/tensors/TestRealTensor.kt | 2 +- .../kmath/tensors/TestRealTensorAlgebra.kt | 14 ++--- 10 files changed, 125 insertions(+), 108 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt index 8399511a5..e56920916 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt @@ -8,6 +8,12 @@ public interface ComplexTensorAlgebra, - RealTensorAlgebra() + DoubleTensorAlgebra() { override fun DoubleTensor.exp(): DoubleTensor { TODO("Not yet implemented") @@ -146,5 +146,5 @@ public class RealAnalyticTensorAlgebra: } -public inline fun RealAnalyticTensorAlgebra(block: RealAnalyticTensorAlgebra.() -> R): R = - RealAnalyticTensorAlgebra().block() \ No newline at end of file +public inline fun DoubleAnalyticTensorAlgebra(block: DoubleAnalyticTensorAlgebra.() -> R): R = + DoubleAnalyticTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt index ddb3dfa12..1aaf8df9d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt @@ -2,27 +2,12 @@ package space.kscience.kmath.tensors public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, - RealTensorAlgebra() { - override fun eye(n: Int): DoubleTensor { - val shape = intArrayOf(n, n) - val buffer = DoubleArray(n * n) { 0.0 } - val res = DoubleTensor(shape, buffer) - for (i in 0 until n) { - res[intArrayOf(i, i)] = 1.0 - } - return res + DoubleTensorAlgebra() { + + override fun DoubleTensor.inv(): DoubleTensor { + TODO("Not yet implemented") } - - override fun DoubleTensor.dot(other: DoubleTensor): DoubleTensor { - TODO("Alya") - } - - override fun diagonalEmbedding(diagonalEntries: DoubleTensor, offset: Int, dim1: Int, dim2: Int): DoubleTensor { - TODO("Alya") - } - - override fun DoubleTensor.lu(): Pair { // todo checks val luTensor = this.copy() @@ -115,15 +100,6 @@ public class DoubleLinearOpsTensorAlgebra : return Triple(p, l, u) } - override fun DoubleTensor.det(): DoubleTensor { - - TODO("Not yet implemented") - } - - override fun DoubleTensor.inv(): DoubleTensor { - TODO("Not yet implemented") - } - override fun DoubleTensor.cholesky(): DoubleTensor { TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt new file mode 100644 index 000000000..e7ebf6c56 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt @@ -0,0 +1,41 @@ +package space.kscience.kmath.tensors + +public class DoubleOrderedTensorAlgebra: + OrderedTensorAlgebra, + DoubleTensorAlgebra() +{ + override fun DoubleTensor.max(dim: Int, keepDim: Boolean): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.cummax(dim: Int): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.min(dim: Int, keepDim: Boolean): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.cummin(dim: Int): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.median(dim: Int, keepDim: Boolean): DoubleTensor { + TODO("Not yet implemented") + } + + override fun maximum(lhs: DoubleTensor, rhs: DoubleTensor) { + TODO("Not yet implemented") + } + + override fun minimum(lhs: DoubleTensor, rhs: DoubleTensor) { + TODO("Not yet implemented") + } + + override fun DoubleTensor.sort(dim: Int, keepDim: Boolean, descending: Boolean): DoubleTensor { + TODO("Not yet implemented") + } +} + +public inline fun DoubleOrderedTensorAlgebra(block: DoubleOrderedTensorAlgebra.() -> R): R = + DoubleOrderedTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index dd15a257c..8b9701127 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.tensors -public open class RealTensorAlgebra : TensorPartialDivisionAlgebra { +public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun DoubleTensor.value(): Double { check(this.shape contentEquals intArrayOf(1)) { @@ -27,6 +27,15 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra, dim: Int): DoubleTensor { @@ -276,7 +261,11 @@ public open class RealTensorAlgebra : TensorPartialDivisionAlgebra RealTensorAlgebra(block: RealTensorAlgebra.() -> R): R = - RealTensorAlgebra().block() \ No newline at end of file +public inline fun DoubleTensorAlgebra(block: DoubleTensorAlgebra.() -> R): R = + DoubleTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index db1135a33..7450c09c1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -4,21 +4,6 @@ package space.kscience.kmath.tensors public interface LinearOpsTensorAlgebra> : TensorPartialDivisionAlgebra { - //https://pytorch.org/docs/stable/generated/torch.eye.html - public fun eye(n: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.matmul.html - public infix fun TensorType.dot(other: TensorType): TensorType - - //https://pytorch.org/docs/stable/generated/torch.diag_embed.html - public fun diagonalEmbedding( - diagonalEntries: TensorType, - offset: Int = 0, dim1: Int = -2, dim2: Int = -1 - ): TensorType - - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det - public fun TensorType.det(): TensorType - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv public fun TensorType.inv(): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt new file mode 100644 index 000000000..3320c3a1e --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt @@ -0,0 +1,29 @@ +package space.kscience.kmath.tensors + +public interface OrderedTensorAlgebra> : + TensorAlgebra { + + //https://pytorch.org/docs/stable/generated/torch.max.html#torch.max + public fun TensorType.max(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cummax.html#torch.cummax + public fun TensorType.cummax(dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.min.html#torch.min + public fun TensorType.min(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.cummin.html#torch.cummin + public fun TensorType.cummin(dim: Int): TensorType + + //https://pytorch.org/docs/stable/generated/torch.median.html#torch.median + public fun TensorType.median(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.maximum.html#torch.maximum + public fun maximum(lhs: TensorType, rhs: TensorType) + + //https://pytorch.org/docs/stable/generated/torch.minimum.html#torch.minimum + public fun minimum(lhs: TensorType, rhs: TensorType) + + //https://pytorch.org/docs/stable/generated/torch.sort.html#torch.sort + public fun TensorType.sort(dim: Int, keepDim: Boolean, descending: Boolean): TensorType +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index a53054e21..6f368f332 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -17,6 +17,9 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.full_like.html#torch.full_like public fun TensorType.fullLike(value: T): TensorType + //https://pytorch.org/docs/stable/generated/torch.eye.html + public fun eye(n: Int): TensorType + public fun TensorType.copy(): TensorType public operator fun T.plus(other: TensorType): TensorType @@ -46,6 +49,9 @@ public interface TensorAlgebra> { public fun TensorType.view(shape: IntArray): TensorType public fun TensorType.viewAs(other: TensorType): TensorType + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det + public fun TensorType.det(): TensorType + //https://pytorch.org/docs/stable/generated/torch.abs.html public fun TensorType.abs(): TensorType @@ -61,29 +67,14 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.cumprod.html#torch.cumprod public fun TensorType.cumprod(dim: Int): TensorType - //https://pytorch.org/docs/stable/generated/torch.max.html#torch.max - public fun TensorType.max(dim: Int, keepDim: Boolean): TensorType + //https://pytorch.org/docs/stable/generated/torch.matmul.html + public infix fun TensorType.dot(other: TensorType): TensorType - //https://pytorch.org/docs/stable/generated/torch.cummax.html#torch.cummax - public fun TensorType.cummax(dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.min.html#torch.min - public fun TensorType.min(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.cummin.html#torch.cummin - public fun TensorType.cummin(dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.median.html#torch.median - public fun TensorType.median(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.maximum.html#torch.maximum - public fun maximum(lhs: TensorType, rhs: TensorType) - - //https://pytorch.org/docs/stable/generated/torch.minimum.html#torch.minimum - public fun minimum(lhs: TensorType, rhs: TensorType) - - //https://pytorch.org/docs/stable/generated/torch.sort.html#torch.sort - public fun TensorType.sort(dim: Int, keepDim: Boolean, descending: Boolean): TensorType + //https://pytorch.org/docs/stable/generated/torch.diag_embed.html + public fun diagonalEmbedding( + diagonalEntries: TensorType, + offset: Int = 0, dim1: Int = -2, dim2: Int = -1 + ): TensorType //https://pytorch.org/docs/stable/generated/torch.cat.html#torch.cat public fun cat(tensors: List, dim: Int): TensorType diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt index 5d42e6d0f..72179ecbc 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensor.kt @@ -9,7 +9,7 @@ import kotlin.test.assertTrue class TestRealTensor { @Test - fun valueTest() = RealTensorAlgebra { + fun valueTest() = DoubleTensorAlgebra { val value = 12.5 val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt index 3e27a1cc2..9dddcf59e 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestRealTensorAlgebra.kt @@ -7,14 +7,14 @@ import kotlin.test.assertTrue class TestRealTensorAlgebra { @Test - fun doublePlus() = RealTensorAlgebra { + fun doublePlus() = DoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(11.0,12.0)) } @Test - fun transpose1x1() = RealTensorAlgebra { + fun transpose1x1() = DoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(0.0)) val res = tensor.transpose(0, 0) @@ -23,7 +23,7 @@ class TestRealTensorAlgebra { } @Test - fun transpose3x2() = RealTensorAlgebra { + fun transpose3x2() = DoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) @@ -32,7 +32,7 @@ class TestRealTensorAlgebra { } @Test - fun transpose1x2x3() = RealTensorAlgebra { + fun transpose1x2x3() = DoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transpose(0, 1) val res02 = tensor.transpose(0, 2) @@ -48,7 +48,7 @@ class TestRealTensorAlgebra { } @Test - fun broadcastShapes() = RealTensorAlgebra { + fun broadcastShapes() = DoubleTensorAlgebra { assertTrue(broadcastShapes( intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) ) contentEquals intArrayOf(1, 2, 3)) @@ -59,7 +59,7 @@ class TestRealTensorAlgebra { } @Test - fun broadcastTensors() = RealTensorAlgebra { + fun broadcastTensors() = DoubleTensorAlgebra { val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -76,7 +76,7 @@ class TestRealTensorAlgebra { } @Test - fun minusTensor() = RealTensorAlgebra { + fun minusTensor() = DoubleTensorAlgebra { val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) From f8e0d4be17baac7e2f5930083b2bfeb7338f99e8 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 21:18:15 +0000 Subject: [PATCH 093/393] MutableStructure 2D & 1D --- .../space/kscience/kmath/nd/Structure1D.kt | 56 +++++++++++++++++++ .../space/kscience/kmath/nd/Structure2D.kt | 53 +++++++++++++++++- .../space/kscience/kmath/structures/Buffer.kt | 5 ++ .../kscience/kmath/tensors/BufferedTensor.kt | 1 - .../kmath/tensors/DoubleTensorAlgebra.kt | 4 ++ .../kscience/kmath/tensors/TensorAlgebra.kt | 2 + .../kscience/kmath/tensors/TensorStructure.kt | 1 - 7 files changed, 118 insertions(+), 4 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 1335a4933..2926b3d1b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -1,6 +1,8 @@ package space.kscience.kmath.nd import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.asMutableBuffer import space.kscience.kmath.structures.asSequence /** @@ -17,6 +19,16 @@ public interface Structure1D : NDStructure, Buffer { public override operator fun iterator(): Iterator = (0 until size).asSequence().map(::get).iterator() } +/** + * A mutable structure that is guaranteed to be one-dimensional + */ +public interface MutableStructure1D : Structure1D, MutableNDStructure, MutableBuffer { + public override operator fun set(index: IntArray, value: T) { + require(index.size == 1) { "Index dimension mismatch. Expected 1 but found ${index.size}" } + set(index[0], value) + } +} + /** * A 1D wrapper for nd-structure */ @@ -28,6 +40,25 @@ private inline class Structure1DWrapper(val structure: NDStructure) : Stru override fun elements(): Sequence> = structure.elements() } +/** + * A 1D wrapper for a mutable nd-structure + */ +private inline class MutableStructure1DWrapper(val structure: MutableNDStructure) : MutableStructure1D { + override val shape: IntArray get() = structure.shape + override val size: Int get() = structure.shape[0] + override fun elements(): Sequence> { + TODO("Not yet implemented") + } + + override fun get(index: Int): T = structure[index] + override fun set(index: Int, value: T) { + set(index, value) + } + + override fun copy(): MutableBuffer = + structure.elements().map { it.second }.toMutableList().asMutableBuffer() +} + /** * A structure wrapper for buffer @@ -42,6 +73,21 @@ private inline class Buffer1DWrapper(val buffer: Buffer) : Structure1D override operator fun get(index: Int): T = buffer[index] } +private inline class MutableBuffer1DWrapper(val buffer: MutableBuffer) : MutableStructure1D { + override val shape: IntArray get() = intArrayOf(buffer.size) + override val size: Int get() = buffer.size + + override fun elements(): Sequence> = + buffer.asSequence().mapIndexed { index, value -> intArrayOf(index) to value } + + override operator fun get(index: Int): T = buffer[index] + override fun set(index: Int, value: T) { + buffer[index] = value + } + + override fun copy(): MutableBuffer = buffer.copy() +} + /** * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch */ @@ -52,7 +98,17 @@ public fun NDStructure.as1D(): Structure1D = this as? Structure1D ? } } else error("Can't create 1d-structure from ${shape.size}d-structure") +public fun MutableNDStructure.as1D(): MutableStructure1D = + this as? MutableStructure1D ?: if (shape.size == 1) { + when (this) { + is MutableNDBuffer -> MutableBuffer1DWrapper(this.buffer) + else -> MutableStructure1DWrapper(this) + } + } else error("Can't create 1d-structure from ${shape.size}d-structure") + /** * Represent this buffer as 1D structure */ public fun Buffer.asND(): Structure1D = Buffer1DWrapper(this) + +public fun MutableBuffer.asND(): MutableStructure1D = MutableBuffer1DWrapper(this) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index e9f8234e5..2f2fd653e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -57,6 +57,20 @@ public interface Structure2D : NDStructure { public companion object } +/** + * Represents mutable [Structure2D]. + */ +public interface MutableStructure2D : Structure2D, MutableNDStructure { + /** + * Inserts an item at the specified indices. + * + * @param i the first index. + * @param j the second index. + * @param value the value. + */ + public operator fun set(i: Int, j: Int, value: T) +} + /** * A 2D wrapper for nd-structure */ @@ -79,11 +93,46 @@ private class Structure2DWrapper(val structure: NDStructure) : Structure2D } /** - * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch + * A 2D wrapper for a mutable nd-structure + */ +private class MutableStructure2DWrapper(val structure: MutableNDStructure): MutableStructure2D +{ + override val shape: IntArray get() = structure.shape + + override val rowNum: Int get() = shape[0] + override val colNum: Int get() = shape[1] + + override operator fun get(i: Int, j: Int): T = structure[i, j] + + override fun set(index: IntArray, value: T) { + structure[index] = value + } + + override operator fun set(i: Int, j: Int, value: T){ + structure[intArrayOf(i, j)] = value + } + + override fun elements(): Sequence> = structure.elements() + + override fun equals(other: Any?): Boolean = false + + override fun hashCode(): Int = 0 +} + +/** + * Represent a [NDStructure] as [Structure2D]. Throw error in case of dimension mismatch */ public fun NDStructure.as2D(): Structure2D = this as? Structure2D ?: when (shape.size) { 2 -> Structure2DWrapper(this) else -> error("Can't create 2d-structure from ${shape.size}d-structure") } -internal fun Structure2D.unwrap(): NDStructure = if (this is Structure2DWrapper) structure else this \ No newline at end of file +internal fun Structure2D.unwrap(): NDStructure = if (this is Structure2DWrapper) structure else this + +public fun MutableNDStructure.as2D(): MutableStructure2D = this as? MutableStructure2D ?: when (shape.size) { + 2 -> MutableStructure2DWrapper(this) + else -> error("Can't create 2d-structure from ${shape.size}d-structure") +} + +internal fun MutableStructure2D.unwrap(): MutableNDStructure = + if (this is MutableStructure2DWrapper) structure else this diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 2bde18fce..c62fa30ba 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -236,6 +236,11 @@ public inline class MutableListBuffer(public val list: MutableList) : Muta override fun copy(): MutableBuffer = MutableListBuffer(ArrayList(list)) } +/** + * Returns an [MutableListBuffer] that wraps the original list. + */ +public fun MutableList.asMutableBuffer(): MutableListBuffer = MutableListBuffer(this) + /** * [MutableBuffer] implementation over [Array]. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index d5adf380c..68fc0412e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -25,7 +25,6 @@ public open class BufferedTensor( this[intArrayOf(i, j)] = value } - } //todo make generator mb nextMatrixIndex? diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 8b9701127..76a3c4c9c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -10,6 +10,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra> { public operator fun TensorType.timesAssign(other: TensorType): Unit public operator fun TensorType.unaryMinus(): TensorType + //https://pytorch.org/cppdocs/notes/tensor_indexing.html + public fun TensorType.get(i: Int): TensorType //https://pytorch.org/docs/stable/generated/torch.transpose.html public fun TensorType.transpose(i: Int, j: Int): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt index 5463877ce..f5ea39d1b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt @@ -3,4 +3,3 @@ package space.kscience.kmath.tensors import space.kscience.kmath.nd.MutableNDStructure public typealias TensorStructure = MutableNDStructure - From 7cb5cd8f71721e5eb5e77e0849311a3fd3c2374f Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 22:11:15 +0000 Subject: [PATCH 094/393] BufferedTensor revisited --- .../kscience/kmath/tensors/BufferedTensor.kt | 54 ++++++++------- .../tensors/DoubleLinearOpsTensorAlgebra.kt | 10 ++- .../kmath/tensors/DoubleTensorAlgebra.kt | 69 ++++++++++--------- .../space/kscience/kmath/tensors/utils.kt | 3 +- ...{TestRealTensor.kt => TestDoubleTensor.kt} | 2 +- ...rAlgebra.kt => TestDoubleTensorAlgebra.kt} | 2 +- 6 files changed, 78 insertions(+), 62 deletions(-) rename kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/{TestRealTensor.kt => TestDoubleTensor.kt} (96%) rename kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/{TestRealTensorAlgebra.kt => TestDoubleTensorAlgebra.kt} (99%) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index 68fc0412e..264692d0c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -1,32 +1,34 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.nd.MutableNDBuffer import space.kscience.kmath.structures.* public open class BufferedTensor( override val shape: IntArray, - buffer: MutableBuffer -) : - TensorStructure, - MutableNDBuffer( - TensorStrides(shape), - buffer - ) { + public val buffer: MutableBuffer, + internal val bufferStart: Int +) : TensorStructure +{ + public val strides: TensorStrides + get() = TensorStrides(shape) + override fun get(index: IntArray): T = buffer[bufferStart + strides.offset(index)] - public operator fun get(i: Int, j: Int): T { - check(this.dimension == 2) { "Not matrix" } - return this[intArrayOf(i, j)] + override fun set(index: IntArray, value: T) { + buffer[bufferStart + strides.offset(index)] = value } - public operator fun set(i: Int, j: Int, value: T): Unit { - check(this.dimension == 2) { "Not matrix" } - this[intArrayOf(i, j)] = value + override fun elements(): Sequence> = strides.indices().map { + it to this[it] } + override fun equals(other: Any?): Boolean = false + + override fun hashCode(): Int = 0 + } +/* //todo make generator mb nextMatrixIndex? public class InnerMatrix(private val tensor: BufferedTensor){ private var offset: Int = 0 @@ -75,25 +77,29 @@ public class InnerVector(private val tensor: BufferedTensor){ offset += step } } - - //todo default buffer = arrayOf(0)??? + */ + public class IntTensor( shape: IntArray, - buffer: IntArray -) : BufferedTensor(shape, IntBuffer(buffer)) + buffer: IntArray, + offset: Int = 0 +) : BufferedTensor(shape, IntBuffer(buffer), offset) public class LongTensor( shape: IntArray, - buffer: LongArray -) : BufferedTensor(shape, LongBuffer(buffer)) + buffer: LongArray, + offset: Int = 0 +) : BufferedTensor(shape, LongBuffer(buffer), offset) public class FloatTensor( shape: IntArray, - buffer: FloatArray -) : BufferedTensor(shape, FloatBuffer(buffer)) + buffer: FloatArray, + offset: Int = 0 +) : BufferedTensor(shape, FloatBuffer(buffer), offset) public class DoubleTensor( shape: IntArray, - buffer: DoubleArray -) : BufferedTensor(shape, RealBuffer(buffer)) \ No newline at end of file + buffer: DoubleArray, + offset: Int = 0 +) : BufferedTensor(shape, RealBuffer(buffer), offset) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt index 1aaf8df9d..eceb28459 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt @@ -9,6 +9,7 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.lu(): Pair { + /* // todo checks val luTensor = this.copy() val lu = InnerMatrix(luTensor) @@ -69,11 +70,13 @@ public class DoubleLinearOpsTensorAlgebra : pivot.makeStep() } - return Pair(luTensor, pivotsTensor) + return Pair(luTensor, pivotsTensor)*/ + + TODO("Andrei, first we need to view and get(Int)") } override fun luPivot(lu: DoubleTensor, pivots: IntTensor): Triple { - + /* // todo checks val n = lu.shape[0] val p = lu.zeroesLike() @@ -97,7 +100,8 @@ public class DoubleLinearOpsTensorAlgebra : } } - return Triple(p, l, u) + return Triple(p, l, u)*/ + TODO("Andrei, first we need implement get(Int)") } override fun DoubleTensor.cholesky(): DoubleTensor { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 76a3c4c9c..391c2895f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -7,11 +7,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.unsafeToDoubleArray()[i] + this + val resBuffer = DoubleArray(other.strides.linearSize) { i -> + other.buffer.unsafeToDoubleArray()[other.bufferStart + i] + this } return DoubleTensor(other.shape, resBuffer) } @@ -60,35 +60,36 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> newThis.buffer.unsafeToDoubleArray()[i] + newOther.buffer.unsafeToDoubleArray()[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun DoubleTensor.plusAssign(value: Double) { - for (i in this.buffer.unsafeToDoubleArray().indices) { - this.buffer.unsafeToDoubleArray()[i] += value + for (i in 0 until this.strides.linearSize) { + this.buffer.unsafeToDoubleArray()[this.bufferStart + i] += value } } override fun DoubleTensor.plusAssign(other: DoubleTensor) { //todo should be change with broadcasting - for (i in this.buffer.unsafeToDoubleArray().indices) { - this.buffer.unsafeToDoubleArray()[i] += other.buffer.unsafeToDoubleArray()[i] + for (i in 0 until this.strides.linearSize) { + this.buffer.unsafeToDoubleArray()[this.bufferStart + i] += + other.buffer.unsafeToDoubleArray()[this.bufferStart + i] } } override fun Double.minus(other: DoubleTensor): DoubleTensor { - val resBuffer = DoubleArray(other.buffer.size) { i -> - this - other.buffer.unsafeToDoubleArray()[i] + val resBuffer = DoubleArray(other.strides.linearSize) { i -> + this - other.buffer.unsafeToDoubleArray()[other.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } override fun DoubleTensor.minus(value: Double): DoubleTensor { - val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.unsafeToDoubleArray()[i] - value + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.unsafeToDoubleArray()[this.bufferStart + i] - value } return DoubleTensor(this.shape, resBuffer) } @@ -97,15 +98,15 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> newThis.buffer.unsafeToDoubleArray()[i] - newOther.buffer.unsafeToDoubleArray()[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun DoubleTensor.minusAssign(value: Double) { - for (i in this.buffer.unsafeToDoubleArray().indices) { - this.buffer.unsafeToDoubleArray()[i] -= value + for (i in 0 until this.strides.linearSize) { + this.buffer.unsafeToDoubleArray()[this.bufferStart + i] -= value } } @@ -115,8 +116,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.unsafeToDoubleArray()[i] * this + val resBuffer = DoubleArray(other.strides.linearSize) { i -> + other.buffer.unsafeToDoubleArray()[other.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) } @@ -126,36 +127,38 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - this.buffer.unsafeToDoubleArray()[i] * other.buffer.unsafeToDoubleArray()[i] + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.unsafeToDoubleArray()[other.bufferStart + i] * + other.buffer.unsafeToDoubleArray()[other.bufferStart + i] } return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.timesAssign(value: Double) { //todo should be change with broadcasting - for (i in this.buffer.unsafeToDoubleArray().indices) { - this.buffer.unsafeToDoubleArray()[i] *= value + for (i in 0 until this.strides.linearSize) { + this.buffer.unsafeToDoubleArray()[this.bufferStart + i] *= value } } override fun DoubleTensor.timesAssign(other: DoubleTensor) { //todo should be change with broadcasting - for (i in this.buffer.unsafeToDoubleArray().indices) { - this.buffer.unsafeToDoubleArray()[i] *= other.buffer.unsafeToDoubleArray()[i] + for (i in 0 until this.strides.linearSize) { + this.buffer.unsafeToDoubleArray()[this.bufferStart + i] *= + other.buffer.unsafeToDoubleArray()[this.bufferStart + i] } } override fun DoubleTensor.unaryMinus(): DoubleTensor { - val resBuffer = DoubleArray(this.buffer.size) { i -> - this.buffer.unsafeToDoubleArray()[i].unaryMinus() + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.unsafeToDoubleArray()[this.bufferStart + i].unaryMinus() } return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.transpose(i: Int, j: Int): DoubleTensor { checkTranspose(this.dimension, i, j) - val n = this.buffer.size + val n = this.strides.linearSize val resBuffer = DoubleArray(n) val resShape = this.shape.copyOf() @@ -169,14 +172,16 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Date: Mon, 15 Mar 2021 22:39:29 +0000 Subject: [PATCH 095/393] get dim 0 operator for tensors --- .../tensors/DoubleLinearOpsTensorAlgebra.kt | 2 +- .../kmath/tensors/DoubleTensorAlgebra.kt | 49 ++++++++++--------- .../kscience/kmath/tensors/TensorAlgebra.kt | 2 +- .../space/kscience/kmath/tensors/utils.kt | 12 ++--- .../kmath/tensors/TestDoubleTensor.kt | 6 +++ .../kmath/tensors/TestDoubleTensorAlgebra.kt | 24 ++++----- 6 files changed, 52 insertions(+), 43 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt index eceb28459..d6b202556 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt @@ -72,7 +72,7 @@ public class DoubleLinearOpsTensorAlgebra : return Pair(luTensor, pivotsTensor)*/ - TODO("Andrei, first we need to view and get(Int)") + TODO("Andrei, use view, get, as2D, as1D") } override fun luPivot(lu: DoubleTensor, pivots: IntTensor): Triple { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 391c2895f..3b65e89da 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -7,11 +7,14 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.unsafeToDoubleArray()[other.bufferStart + i] + this + other.buffer.array()[other.bufferStart + i] + this } return DoubleTensor(other.shape, resBuffer) } @@ -61,35 +64,35 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.unsafeToDoubleArray()[i] + newOther.buffer.unsafeToDoubleArray()[i] + newThis.buffer.array()[i] + newOther.buffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun DoubleTensor.plusAssign(value: Double) { for (i in 0 until this.strides.linearSize) { - this.buffer.unsafeToDoubleArray()[this.bufferStart + i] += value + this.buffer.array()[this.bufferStart + i] += value } } override fun DoubleTensor.plusAssign(other: DoubleTensor) { //todo should be change with broadcasting for (i in 0 until this.strides.linearSize) { - this.buffer.unsafeToDoubleArray()[this.bufferStart + i] += - other.buffer.unsafeToDoubleArray()[this.bufferStart + i] + this.buffer.array()[this.bufferStart + i] += + other.buffer.array()[this.bufferStart + i] } } override fun Double.minus(other: DoubleTensor): DoubleTensor { val resBuffer = DoubleArray(other.strides.linearSize) { i -> - this - other.buffer.unsafeToDoubleArray()[other.bufferStart + i] + this - other.buffer.array()[other.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } override fun DoubleTensor.minus(value: Double): DoubleTensor { val resBuffer = DoubleArray(this.strides.linearSize) { i -> - this.buffer.unsafeToDoubleArray()[this.bufferStart + i] - value + this.buffer.array()[this.bufferStart + i] - value } return DoubleTensor(this.shape, resBuffer) } @@ -99,14 +102,14 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.unsafeToDoubleArray()[i] - newOther.buffer.unsafeToDoubleArray()[i] + newThis.buffer.array()[i] - newOther.buffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun DoubleTensor.minusAssign(value: Double) { for (i in 0 until this.strides.linearSize) { - this.buffer.unsafeToDoubleArray()[this.bufferStart + i] -= value + this.buffer.array()[this.bufferStart + i] -= value } } @@ -117,7 +120,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - other.buffer.unsafeToDoubleArray()[other.bufferStart + i] * this + other.buffer.array()[other.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) } @@ -128,8 +131,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - this.buffer.unsafeToDoubleArray()[other.bufferStart + i] * - other.buffer.unsafeToDoubleArray()[other.bufferStart + i] + this.buffer.array()[other.bufferStart + i] * + other.buffer.array()[other.bufferStart + i] } return DoubleTensor(this.shape, resBuffer) } @@ -137,21 +140,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - this.buffer.unsafeToDoubleArray()[this.bufferStart + i].unaryMinus() + this.buffer.array()[this.bufferStart + i].unaryMinus() } return DoubleTensor(this.shape, resBuffer) } @@ -172,8 +175,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra> { public operator fun TensorType.unaryMinus(): TensorType //https://pytorch.org/cppdocs/notes/tensor_indexing.html - public fun TensorType.get(i: Int): TensorType + public operator fun TensorType.get(i: Int): TensorType //https://pytorch.org/docs/stable/generated/torch.transpose.html public fun TensorType.transpose(i: Int, j: Int): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt index 74a774f45..3e32e2b72 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt @@ -55,8 +55,8 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List, /** * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. */ -internal fun Buffer.unsafeToIntArray(): IntArray = when(this) { +internal fun Buffer.array(): IntArray = when(this) { is IntBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to IntArray") } @@ -107,7 +107,7 @@ internal fun Buffer.unsafeToIntArray(): IntArray = when(this) { /** * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. */ -internal fun Buffer.unsafeToLongArray(): LongArray = when(this) { +internal fun Buffer.array(): LongArray = when(this) { is LongBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to LongArray") } @@ -115,7 +115,7 @@ internal fun Buffer.unsafeToLongArray(): LongArray = when(this) { /** * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. */ -internal fun Buffer.unsafeToFloatArray(): FloatArray = when(this) { +internal fun Buffer.array(): FloatArray = when(this) { is FloatBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to FloatArray") } @@ -123,7 +123,7 @@ internal fun Buffer.unsafeToFloatArray(): FloatArray = when(this) { /** * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. */ -internal fun Buffer.unsafeToDoubleArray(): DoubleArray = when(this) { +internal fun Buffer.array(): DoubleArray = when(this) { is RealBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt index 31c6ccbbf..b1c8cd6dd 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt @@ -21,4 +21,10 @@ class TestDoubleTensor { assertEquals(tensor[intArrayOf(0,1)], 5.8) assertTrue(tensor.elements().map{ it.second }.toList().toDoubleArray() contentEquals tensor.buffer.toDoubleArray()) } + + @Test + fun getTest() = DoubleTensorAlgebra { + val tensor = DoubleTensor(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) + assertTrue(tensor[0].elements().map{ it.second }.toList().toDoubleArray() contentEquals doubleArrayOf(3.5,5.8)) + } } \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt index 91181484c..226454bf4 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt @@ -10,7 +10,7 @@ class TestDoubleTensorAlgebra { fun doublePlus() = DoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor - assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(11.0,12.0)) + assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0,12.0)) } @Test @@ -18,7 +18,7 @@ class TestDoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(0.0)) val res = tensor.transpose(0, 0) - assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(0.0)) + assertTrue(res.buffer.array() contentEquals doubleArrayOf(0.0)) assertTrue(res.shape contentEquals intArrayOf(1)) } @@ -27,7 +27,7 @@ class TestDoubleTensorAlgebra { val tensor = DoubleTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) - assertTrue(res.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) + assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) assertTrue(res.shape contentEquals intArrayOf(2, 3)) } @@ -42,9 +42,9 @@ class TestDoubleTensorAlgebra { assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2)) - assertTrue(res01.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res02.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) - assertTrue(res12.buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res01.buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res02.buffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res12.buffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) } @Test @@ -70,9 +70,9 @@ class TestDoubleTensorAlgebra { assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[0].buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res[1].buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) - assertTrue(res[2].buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) + assertTrue(res[0].buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + assertTrue(res[2].buffer.array() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) } @Test @@ -82,14 +82,14 @@ class TestDoubleTensorAlgebra { val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) assertTrue((tensor2 - tensor1).shape contentEquals intArrayOf(2, 3)) - assertTrue((tensor2 - tensor1).buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) + assertTrue((tensor2 - tensor1).buffer.array() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) assertTrue((tensor3 - tensor1).shape contentEquals intArrayOf(1, 2, 3)) - assertTrue((tensor3 - tensor1).buffer.unsafeToDoubleArray() + assertTrue((tensor3 - tensor1).buffer.array() contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0)) assertTrue((tensor3 - tensor2).shape contentEquals intArrayOf(1, 1, 3)) - assertTrue((tensor3 - tensor2).buffer.unsafeToDoubleArray() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) + assertTrue((tensor3 - tensor2).buffer.array() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) } } \ No newline at end of file From f4454a6cf6b8d54b1ecd818e2c39e6287b382189 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 15 Mar 2021 22:45:55 +0000 Subject: [PATCH 096/393] Matrices from tensors test --- .../kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt index b1c8cd6dd..3050f064a 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray import kotlin.test.Test import kotlin.test.assertEquals @@ -24,7 +25,8 @@ class TestDoubleTensor { @Test fun getTest() = DoubleTensorAlgebra { - val tensor = DoubleTensor(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) - assertTrue(tensor[0].elements().map{ it.second }.toList().toDoubleArray() contentEquals doubleArrayOf(3.5,5.8)) + val tensor = DoubleTensor(intArrayOf(1,2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) + val matrix = tensor[0].as2D() + assertEquals(matrix[0,1], 5.8) } } \ No newline at end of file From 0553a28ee89e0d55f498c578882fece47bc620fe Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 16 Mar 2021 07:47:02 +0000 Subject: [PATCH 097/393] ReduceOpsTensorAlgebra --- .../kmath/tensors/AnalyticTensorAlgebra.kt | 15 +++++++++++- .../tensors/DoubleAnalyticTensorAlgebra.kt | 18 ++++++++++++++- .../tensors/DoubleOrderedTensorAlgebra.kt | 2 +- .../tensors/DoubleReduceOpsTensorAlgebra.kt | 16 +++++++++++++ .../kmath/tensors/DoubleTensorAlgebra.kt | 23 ------------------- .../kmath/tensors/ReduceOpsTensorAlgebra.kt | 7 ++++++ .../kscience/kmath/tensors/TensorAlgebra.kt | 1 - .../tensors/TensorPartialDivisionAlgebra.kt | 14 ----------- .../kmath/tensors/TestDoubleTensor.kt | 12 +++++++++- 9 files changed, 66 insertions(+), 42 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ReduceOpsTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt index 17a25b6b3..41772da44 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt @@ -2,7 +2,17 @@ package space.kscience.kmath.tensors public interface AnalyticTensorAlgebra> : - TensorPartialDivisionAlgebra { + TensorPartialDivisionAlgebra, + OrderedTensorAlgebra{ + + //https://pytorch.org/docs/stable/generated/torch.quantile.html#torch.quantile + public fun TensorType.quantile(q: T, dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.std.html#torch.std + public fun TensorType.std(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var + public fun TensorType.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType //https://pytorch.org/docs/stable/generated/torch.exp.html public fun TensorType.exp(): TensorType @@ -109,4 +119,7 @@ public interface AnalyticTensorAlgebra> : //https://pytorch.org/docs/stable/generated/torch.trapz.html#torch.trapz public fun TensorType.trapz(xValues: TensorType, dim: Int): TensorType + //https://pytorch.org/docs/stable/generated/torch.histc.html#torch.histc + public fun TensorType.histc(bins: Int, min: T, max: T): TensorType + } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt index 00e7a7fbd..cccc02789 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.tensors public class DoubleAnalyticTensorAlgebra: AnalyticTensorAlgebra, - DoubleTensorAlgebra() + DoubleOrderedTensorAlgebra() { override fun DoubleTensor.exp(): DoubleTensor { TODO("Not yet implemented") @@ -144,6 +144,22 @@ public class DoubleAnalyticTensorAlgebra: TODO("Not yet implemented") } + override fun DoubleTensor.quantile(q: Double, dim: Int, keepDim: Boolean): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.std(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { + TODO("Not yet implemented") + } + + override fun DoubleTensor.histc(bins: Int, min: Double, max: Double): DoubleTensor { + TODO("Not yet implemented") + } + } public inline fun DoubleAnalyticTensorAlgebra(block: DoubleAnalyticTensorAlgebra.() -> R): R = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt index e7ebf6c56..bd6bcfe8f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.tensors -public class DoubleOrderedTensorAlgebra: +public open class DoubleOrderedTensorAlgebra: OrderedTensorAlgebra, DoubleTensorAlgebra() { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt new file mode 100644 index 000000000..00d9b3ff8 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt @@ -0,0 +1,16 @@ +package space.kscience.kmath.tensors + +public class DoubleReduceOpsTensorAlgebra: + DoubleTensorAlgebra(), + ReduceOpsTensorAlgebra { + + override fun DoubleTensor.value(): Double { + check(this.shape contentEquals intArrayOf(1)) { + "Inconsistent value for tensor of shape ${shape.toList()}" + } + return this.buffer.array()[this.bufferStart] + } +} + +public inline fun DoubleReduceOpsTensorAlgebra(block: DoubleReduceOpsTensorAlgebra.() -> R): R = + DoubleReduceOpsTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 3b65e89da..c383387ef 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -3,13 +3,6 @@ package space.kscience.kmath.tensors public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { - override fun DoubleTensor.value(): Double { - check(this.shape contentEquals intArrayOf(1)) { - "Inconsistent value for tensor of shape ${shape.toList()}" - } - return this.buffer.array()[this.bufferStart] - } - override operator fun DoubleTensor.get(i: Int): DoubleTensor { val lastShape = this.shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) @@ -257,22 +250,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra> : + TensorAlgebra { + public fun TensorType.value(): T + +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index e56abfaaa..60f0b3379 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -3,7 +3,6 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { - public fun TensorType.value(): T public fun zeros(shape: IntArray): TensorType public fun TensorType.zeroesLike(): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt index 2d448fa8c..ca3876e2c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -3,7 +3,6 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Division_Algebra public interface TensorPartialDivisionAlgebra> : TensorAlgebra { - public operator fun TensorType.div(value: T): TensorType public operator fun TensorType.div(other: TensorType): TensorType public operator fun TensorType.divAssign(value: T) @@ -11,17 +10,4 @@ public interface TensorPartialDivisionAlgebra //https://pytorch.org/docs/stable/generated/torch.mean.html#torch.mean public fun TensorType.mean(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.quantile.html#torch.quantile - public fun TensorType.quantile(q: T, dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.std.html#torch.std - public fun TensorType.std(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var - public fun TensorType.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.histc.html#torch.histc - public fun TensorType.histc(bins: Int, min: T, max: T): TensorType - } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt index 3050f064a..006b0273a 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray import kotlin.test.Test @@ -10,7 +11,7 @@ import kotlin.test.assertTrue class TestDoubleTensor { @Test - fun valueTest() = DoubleTensorAlgebra { + fun valueTest() = DoubleReduceOpsTensorAlgebra { val value = 12.5 val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) @@ -28,5 +29,14 @@ class TestDoubleTensor { val tensor = DoubleTensor(intArrayOf(1,2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) val matrix = tensor[0].as2D() assertEquals(matrix[0,1], 5.8) + + val vector = tensor[0][1].as1D() + assertEquals(vector[0], 58.4) + + matrix[0,1] = 77.89 + assertEquals(tensor[intArrayOf(0,0,1)], 77.89) + + //vector[0] = 109.56 + //println(tensor[intArrayOf(0,1,0)]) } } \ No newline at end of file From 99ee5aa54a043427d8ade94c82107cdc18e48819 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Tue, 16 Mar 2021 14:57:19 +0300 Subject: [PATCH 098/393] add broadcast to functions --- .../kmath/tensors/DoubleTensorAlgebra.kt | 30 ++++++++------- .../space/kscience/kmath/tensors/utils.kt | 37 +++++++++++++++++++ .../kmath/tensors/TestDoubleTensorAlgebra.kt | 10 +++++ 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index c383387ef..794a06102 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -69,10 +69,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra other.buffer.array()[other.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) } - //todo should be change with broadcasting override fun DoubleTensor.times(value: Double): DoubleTensor = value * this override fun DoubleTensor.times(other: DoubleTensor): DoubleTensor { - //todo should be change with broadcasting - val resBuffer = DoubleArray(this.strides.linearSize) { i -> - this.buffer.array()[other.bufferStart + i] * - other.buffer.array()[other.bufferStart + i] + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + newThis.buffer.array()[newOther.bufferStart + i] * + newOther.buffer.array()[newOther.bufferStart + i] } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(newThis.shape, resBuffer) } override fun DoubleTensor.timesAssign(value: Double) { - //todo should be change with broadcasting for (i in 0 until this.strides.linearSize) { this.buffer.array()[this.bufferStart + i] *= value } } override fun DoubleTensor.timesAssign(other: DoubleTensor) { - //todo should be change with broadcasting + val newOther = broadcastTo(other, this.shape) for (i in 0 until this.strides.linearSize) { this.buffer.array()[this.bufferStart + i] *= - other.buffer.array()[this.bufferStart + i] + newOther.buffer.array()[this.bufferStart + i] } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt index 3e32e2b72..e7e043463 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt @@ -32,6 +32,43 @@ internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { return totalShape } +internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor { + if (tensor.shape.size > newShape.size) { + throw RuntimeException("Tensor is not compatible with the new shape") + } + + val n = newShape.reduce { acc, i -> acc * i } + val resTensor = DoubleTensor(newShape, DoubleArray(n)) + + for (i in tensor.shape.indices) { + val curDim = tensor.shape[i] + val offset = newShape.size - tensor.shape.size + if (curDim != 1 && newShape[i + offset] != curDim) { + throw RuntimeException("Tensor is not compatible with the new shape and cannot be broadcast") + } + } + + for (linearIndex in 0 until n) { + val totalMultiIndex = resTensor.strides.index(linearIndex) + val curMultiIndex = tensor.shape.copyOf() + + val offset = totalMultiIndex.size - curMultiIndex.size + + for (i in curMultiIndex.indices) { + if (curMultiIndex[i] != 1) { + curMultiIndex[i] = totalMultiIndex[i + offset] + } else { + curMultiIndex[i] = 0 + } + } + + val curLinearIndex = tensor.strides.offset(curMultiIndex) + resTensor.buffer.array()[linearIndex] = + tensor.buffer.array()[tensor.bufferStart + curLinearIndex] + } + return resTensor +} + internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List { val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) val n = totalShape.reduce { acc, i -> acc * i } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt index 226454bf4..a060a970f 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt @@ -58,6 +58,16 @@ class TestDoubleTensorAlgebra { ) contentEquals intArrayOf(5, 6, 7)) } + @Test + fun broadcastTo() = DoubleTensorAlgebra { + val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + + val res = broadcastTo(tensor2, tensor1.shape) + assertTrue(res.shape contentEquals intArrayOf(2, 3)) + assertTrue(res.buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + } + @Test fun broadcastTensors() = DoubleTensorAlgebra { val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) From 874875c13aaf79f6a27fa6c1f19f9f264bc53c19 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 16 Mar 2021 15:05:44 +0300 Subject: [PATCH 099/393] API for integration --- .../kmath/commons/integration/CMIntegrator.kt | 77 +++++++++++++++ .../integration/GaussRuleIntegrator.kt | 94 +++++++++++++++++++ .../commons/integration/IntegrationTest.kt | 30 ++++++ .../kscience/kmath/integration/Integrand.kt | 17 +++- .../kscience/kmath/integration/Integrator.kt | 11 +++ .../integration/MultivariateIntegrand.kt | 27 ++++++ .../kmath/integration/UnivariateIntegrand.kt | 64 +++++++++++++ 7 files changed, 318 insertions(+), 2 deletions(-) create mode 100644 kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt create mode 100644 kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt create mode 100644 kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt new file mode 100644 index 000000000..e2ed84f1a --- /dev/null +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt @@ -0,0 +1,77 @@ +package space.kscience.kmath.commons.integration + +import org.apache.commons.math3.analysis.integration.IterativeLegendreGaussIntegrator +import org.apache.commons.math3.analysis.integration.SimpsonIntegrator +import space.kscience.kmath.integration.* + +/** + * Integration wrapper for Common-maths UnivariateIntegrator + */ +public class CMIntegrator( + private val defaultMaxCalls: Int = 200, + public val integratorBuilder: (Integrand) -> org.apache.commons.math3.analysis.integration.UnivariateIntegrator, +) : UnivariateIntegrator { + + public class TargetRelativeAccuracy(public val value: Double) : IntegrandFeature + public class TargetAbsoluteAccuracy(public val value: Double) : IntegrandFeature + + public class MinIterations(public val value: Int) : IntegrandFeature + public class MaxIterations(public val value: Int) : IntegrandFeature + + override fun evaluate(integrand: UnivariateIntegrand): UnivariateIntegrand { + val integrator = integratorBuilder(integrand) + val maxCalls = integrand.getFeature()?.maxCalls ?: defaultMaxCalls + val remainingCalls = maxCalls - integrand.calls + val range = integrand.getFeature>()?.range + ?: error("Integration range is not provided") + val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive) + + return integrand + + IntegrandValue(res) + + IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy) + + IntegrandRelativeAccuracy(integrator.relativeAccuracy) + + IntegrandCalls(integrator.evaluations + integrand.calls) + } + + + public companion object { + /** + * Create a Simpson integrator based on [SimpsonIntegrator] + */ + public fun simpson(defaultMaxCalls: Int = 200): CMIntegrator = CMIntegrator(defaultMaxCalls) { integrand -> + val absoluteAccuracy = integrand.getFeature()?.value + ?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY + val relativeAccuracy = integrand.getFeature()?.value + ?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY + val minIterations = integrand.getFeature()?.value + ?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT + val maxIterations = integrand.getFeature()?.value + ?: SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT + + SimpsonIntegrator(relativeAccuracy, absoluteAccuracy, minIterations, maxIterations) + } + + /** + * Create a Gauss-Legandre integrator based on [IterativeLegendreGaussIntegrator] + */ + public fun legandre(numPoints: Int, defaultMaxCalls: Int = numPoints * 5): CMIntegrator = + CMIntegrator(defaultMaxCalls) { integrand -> + val absoluteAccuracy = integrand.getFeature()?.value + ?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY + val relativeAccuracy = integrand.getFeature()?.value + ?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY + val minIterations = integrand.getFeature()?.value + ?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT + val maxIterations = integrand.getFeature()?.value + ?: IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT + + IterativeLegendreGaussIntegrator( + numPoints, + relativeAccuracy, + absoluteAccuracy, + minIterations, + maxIterations + ) + } + } +} \ No newline at end of file diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt new file mode 100644 index 000000000..29df2e787 --- /dev/null +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt @@ -0,0 +1,94 @@ +/* + * Copyright 2015 Alexander Nozik. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package space.kscience.kmath.commons.integration + +import org.apache.commons.math3.analysis.integration.gauss.GaussIntegrator +import org.apache.commons.math3.analysis.integration.gauss.GaussIntegratorFactory +import space.kscience.kmath.integration.* + +/** + * A simple one-pass integrator based on Gauss rule + */ +public class GaussRuleIntegrator( + private val numpoints: Int, + private var type: GaussRule = GaussRule.LEGANDRE, +) : UnivariateIntegrator { + + override fun evaluate(integrand: UnivariateIntegrand): UnivariateIntegrand { + val range = integrand.getFeature>()?.range + ?: error("Integration range is not provided") + val integrator: GaussIntegrator = getIntegrator(range) + //TODO check performance + val res: Double = integrator.integrate(integrand.function) + return integrand + IntegrandValue(res) + IntegrandCalls(integrand.calls + numpoints) + } + + private fun getIntegrator(range: ClosedRange): GaussIntegrator { + return when (type) { + GaussRule.LEGANDRE -> factory.legendre( + numpoints, + range.start, + range.endInclusive + ) + GaussRule.LEGANDREHP -> factory.legendreHighPrecision( + numpoints, + range.start, + range.endInclusive + ) + GaussRule.UNIFORM -> GaussIntegrator( + getUniformRule( + range.start, + range.endInclusive, + numpoints + ) + ) + } + } + + private fun getUniformRule( + min: Double, + max: Double, + numPoints: Int, + ): org.apache.commons.math3.util.Pair { + assert(numPoints > 2) + val points = DoubleArray(numPoints) + val weights = DoubleArray(numPoints) + val step = (max - min) / (numPoints - 1) + points[0] = min + for (i in 1 until numPoints) { + points[i] = points[i - 1] + step + weights[i] = step + } + return org.apache.commons.math3.util.Pair(points, weights) + } + + public enum class GaussRule { + UNIFORM, LEGANDRE, LEGANDREHP + } + + public companion object { + private val factory: GaussIntegratorFactory = GaussIntegratorFactory() + + public fun integrate( + range: ClosedRange, + numPoints: Int = 100, + type: GaussRule = GaussRule.LEGANDRE, + function: (Double) -> Double, + ): Double = GaussRuleIntegrator(numPoints, type).evaluate( + UnivariateIntegrand(function, IntegrationRange(range)) + ).value!! + } +} \ No newline at end of file diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt new file mode 100644 index 000000000..671acce07 --- /dev/null +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt @@ -0,0 +1,30 @@ +package space.kscience.kmath.commons.integration + +import org.junit.jupiter.api.Test +import space.kscience.kmath.integration.integrate +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.RealField.sin +import kotlin.math.PI +import kotlin.math.abs +import kotlin.test.assertTrue + +@UnstableKMathAPI +internal class IntegrationTest { + private val function: (Double) -> Double = { sin(it) } + + @Test + fun simpson() { + val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function) + assertTrue { abs(res) < 1e-3 } + } + + @Test + fun customSimpson() { + val res = CMIntegrator.simpson().integrate(0.0..PI, function) { + add(CMIntegrator.TargetRelativeAccuracy(1e-4)) + add(CMIntegrator.TargetAbsoluteAccuracy(1e-4)) + } + assertTrue { abs(res - 2) < 1e-3 } + assertTrue { abs(res - 2) > 1e-12 } + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt index 31006cde2..ae964b271 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt @@ -5,5 +5,18 @@ import kotlin.reflect.KClass public interface IntegrandFeature public interface Integrand { - public fun getFeature(type: KClass): T? = null -} \ No newline at end of file + public fun getFeature(type: KClass): T? +} + +public inline fun Integrand.getFeature(): T? = getFeature(T::class) + +public class IntegrandValue(public val value: T) : IntegrandFeature + +public class IntegrandRelativeAccuracy(public val accuracy: Double) : IntegrandFeature + +public class IntegrandAbsoluteAccuracy(public val accuracy: Double) : IntegrandFeature + +public class IntegrandCalls(public val calls: Int) : IntegrandFeature +public val Integrand.calls: Int get() = getFeature()?.calls ?: 0 + +public class IntegrandMaxCalls(public val maxCalls: Int) : IntegrandFeature diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt new file mode 100644 index 000000000..39330e91e --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt @@ -0,0 +1,11 @@ +package space.kscience.kmath.integration + +/** + * A general interface for all integrators + */ +public interface Integrator { + /** + * Run one integration pass and return a new [Integrand] with a new set of features + */ + public fun evaluate(integrand: I): I +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt new file mode 100644 index 000000000..4b3a6deb4 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt @@ -0,0 +1,27 @@ +package space.kscience.kmath.integration + +import space.kscience.kmath.linear.Point +import kotlin.reflect.KClass + +public class MultivariateIntegrand internal constructor( + private val features: Map, IntegrandFeature>, + public val function: (Point) -> T, +) : Integrand { + + @Suppress("UNCHECKED_CAST") + override fun getFeature(type: KClass): T? = features[type] as? T + + public operator fun plus(pair: Pair, F>): MultivariateIntegrand = + MultivariateIntegrand(features + pair, function) + + public operator fun plus(feature: F): MultivariateIntegrand = + plus(feature::class to feature) +} + +@Suppress("FunctionName") +public fun MultivariateIntegrand( + vararg features: IntegrandFeature, + function: (Point) -> T, +): MultivariateIntegrand = MultivariateIntegrand(features.associateBy { it::class }, function) + +public val MultivariateIntegrand.value: T? get() = getFeature>()?.value diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt new file mode 100644 index 000000000..ac9c570bc --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -0,0 +1,64 @@ +package space.kscience.kmath.integration + +import space.kscience.kmath.misc.UnstableKMathAPI +import kotlin.reflect.KClass + +public class UnivariateIntegrand internal constructor( + private val features: Map, IntegrandFeature>, + public val function: (T) -> T, +) : Integrand { + + @Suppress("UNCHECKED_CAST") + override fun getFeature(type: KClass): T? = features[type] as? T + + public operator fun plus(pair: Pair, F>): UnivariateIntegrand = + UnivariateIntegrand(features + pair, function) + + public operator fun plus(feature: F): UnivariateIntegrand = + plus(feature::class to feature) +} + +@Suppress("FunctionName") +public fun UnivariateIntegrand( + function: (T) -> T, + vararg features: IntegrandFeature, +): UnivariateIntegrand = UnivariateIntegrand(features.associateBy { it::class }, function) + +public typealias UnivariateIntegrator = Integrator> + +public inline class IntegrationRange>(public val range: ClosedRange) : IntegrandFeature + +public val UnivariateIntegrand.value: T? get() = getFeature>()?.value + +/** + * A shortcut method to integrate a [function] in [range] with additional [features]. + * The [function] is placed in the end position to allow passing a lambda. + */ +@UnstableKMathAPI +public fun UnivariateIntegrator.integrate( + range: ClosedRange, + vararg features: IntegrandFeature, + function: (Double) -> Double, +): Double = evaluate( + UnivariateIntegrand(function, IntegrationRange(range), *features) +).value ?: error("Unexpected: no value after integration.") + +/** + * A shortcut method to integrate a [function] in [range] with additional [features]. + * The [function] is placed in the end position to allow passing a lambda. + */ +@UnstableKMathAPI +public fun UnivariateIntegrator.integrate( + range: ClosedRange, + function: (Double) -> Double, + featureBuilder: (MutableList.() -> Unit) = {}, +): Double { + //TODO use dedicated feature builder class instead or add extensions to MutableList + val features = buildList { + featureBuilder() + add(IntegrationRange(range)) + } + return evaluate( + UnivariateIntegrand(function, *features.toTypedArray()) + ).value ?: error("Unexpected: no value after integration.") +} \ No newline at end of file From 70bebbe8488840a38e84855ca3d3eea1ddb4eebb Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 16 Mar 2021 12:12:28 +0000 Subject: [PATCH 100/393] 1D mutable structure setter fixed --- .../kotlin/space/kscience/kmath/nd/Structure1D.kt | 2 +- .../space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt | 6 ------ .../kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt | 8 -------- .../space/kscience/kmath/tensors/DoubleTensorAlgebra.kt | 8 ++++++++ .../kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt | 3 +++ .../kmath/tensors/TensorPartialDivisionAlgebra.kt | 3 +++ .../space/kscience/kmath/tensors/TestDoubleTensor.kt | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 2926b3d1b..fd965a668 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -52,7 +52,7 @@ private inline class MutableStructure1DWrapper(val structure: MutableNDStruct override fun get(index: Int): T = structure[index] override fun set(index: Int, value: T) { - set(index, value) + structure[intArrayOf(index)] = value } override fun copy(): MutableBuffer = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt index 41772da44..c3a558298 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt @@ -11,9 +11,6 @@ public interface AnalyticTensorAlgebra> : //https://pytorch.org/docs/stable/generated/torch.std.html#torch.std public fun TensorType.std(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType - //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var - public fun TensorType.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType - //https://pytorch.org/docs/stable/generated/torch.exp.html public fun TensorType.exp(): TensorType @@ -23,9 +20,6 @@ public interface AnalyticTensorAlgebra> : //https://pytorch.org/docs/stable/generated/torch.sqrt.html public fun TensorType.sqrt(): TensorType - //https://pytorch.org/docs/stable/generated/torch.square.html - public fun TensorType.square(): TensorType - //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos public fun TensorType.cos(): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt index cccc02789..5349a9923 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt @@ -16,10 +16,6 @@ public class DoubleAnalyticTensorAlgebra: TODO("Not yet implemented") } - override fun DoubleTensor.square(): DoubleTensor { - TODO("Not yet implemented") - } - override fun DoubleTensor.cos(): DoubleTensor { TODO("Not yet implemented") } @@ -152,10 +148,6 @@ public class DoubleAnalyticTensorAlgebra: TODO("Not yet implemented") } - override fun DoubleTensor.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - override fun DoubleTensor.histc(bins: Int, min: Double, max: Double): DoubleTensor { TODO("Not yet implemented") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index c383387ef..bafbd9a96 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -254,6 +254,14 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra DoubleTensorAlgebra(block: DoubleTensorAlgebra.() -> R): R = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 60f0b3379..0af757d1a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -40,6 +40,9 @@ public interface TensorAlgebra> { public operator fun TensorType.timesAssign(other: TensorType): Unit public operator fun TensorType.unaryMinus(): TensorType + //https://pytorch.org/docs/stable/generated/torch.square.html + public fun TensorType.square(): TensorType + //https://pytorch.org/cppdocs/notes/tensor_indexing.html public operator fun TensorType.get(i: Int): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt index ca3876e2c..9f70f9621 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -10,4 +10,7 @@ public interface TensorPartialDivisionAlgebra //https://pytorch.org/docs/stable/generated/torch.mean.html#torch.mean public fun TensorType.mean(dim: Int, keepDim: Boolean): TensorType + + //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var + public fun TensorType.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt index 006b0273a..6b20027c7 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt @@ -36,7 +36,7 @@ class TestDoubleTensor { matrix[0,1] = 77.89 assertEquals(tensor[intArrayOf(0,0,1)], 77.89) - //vector[0] = 109.56 - //println(tensor[intArrayOf(0,1,0)]) + vector[0] = 109.56 + assertEquals(tensor[intArrayOf(0,1,0)], 109.56) } } \ No newline at end of file From bd3425e7a545622c117740bba178ec1b1b531eab Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 16 Mar 2021 14:43:20 +0000 Subject: [PATCH 101/393] IndexTensor type added to LinearOps --- .../kotlin/space/kscience/kmath/tensors/BufferedTensor.kt | 3 +++ .../kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt | 2 +- .../space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index 264692d0c..c9a401ad5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -12,6 +12,9 @@ public open class BufferedTensor( public val strides: TensorStrides get() = TensorStrides(shape) + public val numel: Int + get() = strides.linearSize + override fun get(index: IntArray): T = buffer[bufferStart + strides.offset(index)] override fun set(index: IntArray, value: T) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt index d6b202556..689eda9e0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.tensors public class DoubleLinearOpsTensorAlgebra : - LinearOpsTensorAlgebra, + LinearOpsTensorAlgebra, DoubleTensorAlgebra() { override fun DoubleTensor.inv(): DoubleTensor { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index 7450c09c1..2e1c4a92c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.tensors -public interface LinearOpsTensorAlgebra> : +public interface LinearOpsTensorAlgebra, IndexTensorType: TensorStructure> : TensorPartialDivisionAlgebra { //https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv @@ -14,7 +14,7 @@ public interface LinearOpsTensorAlgebra> : public fun TensorType.qr(): TensorType //https://pytorch.org/docs/stable/generated/torch.lu.html - public fun TensorType.lu(): Pair + public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html public fun luPivot(lu: TensorType, pivots: IntTensor): Triple From 105b84b87cd9e22a0c1f40916f053d3cf257a0fc Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 16 Mar 2021 20:44:03 +0300 Subject: [PATCH 102/393] minor cosmetics --- .../kmath/commons/integration/CMIntegrator.kt | 19 +++++++++++++++++-- .../integration/GaussRuleIntegrator.kt | 4 ++-- .../optimization/CMOptimizationProblem.kt | 2 +- .../commons/integration/IntegrationTest.kt | 4 ++-- .../kscience/kmath/integration/Integrator.kt | 2 +- .../kmath/integration/UnivariateIntegrand.kt | 4 ++-- 6 files changed, 25 insertions(+), 10 deletions(-) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt index e2ed84f1a..8511ed66e 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt @@ -3,6 +3,7 @@ package space.kscience.kmath.commons.integration import org.apache.commons.math3.analysis.integration.IterativeLegendreGaussIntegrator import org.apache.commons.math3.analysis.integration.SimpsonIntegrator import space.kscience.kmath.integration.* +import space.kscience.kmath.misc.UnstableKMathAPI /** * Integration wrapper for Common-maths UnivariateIntegrator @@ -18,7 +19,7 @@ public class CMIntegrator( public class MinIterations(public val value: Int) : IntegrandFeature public class MaxIterations(public val value: Int) : IntegrandFeature - override fun evaluate(integrand: UnivariateIntegrand): UnivariateIntegrand { + override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand { val integrator = integratorBuilder(integrand) val maxCalls = integrand.getFeature()?.maxCalls ?: defaultMaxCalls val remainingCalls = maxCalls - integrand.calls @@ -74,4 +75,18 @@ public class CMIntegrator( ) } } -} \ No newline at end of file +} + +@UnstableKMathAPI +public var MutableList.targetAbsoluteAccuracy: Double? + get() = filterIsInstance().lastOrNull()?.value + set(value){ + value?.let { add(CMIntegrator.TargetAbsoluteAccuracy(value))} + } + +@UnstableKMathAPI +public var MutableList.targetRelativeAccuracy: Double? + get() = filterIsInstance().lastOrNull()?.value + set(value){ + value?.let { add(CMIntegrator.TargetRelativeAccuracy(value))} + } \ No newline at end of file diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt index 29df2e787..5a18756ac 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt @@ -27,7 +27,7 @@ public class GaussRuleIntegrator( private var type: GaussRule = GaussRule.LEGANDRE, ) : UnivariateIntegrator { - override fun evaluate(integrand: UnivariateIntegrand): UnivariateIntegrand { + override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand { val range = integrand.getFeature>()?.range ?: error("Integration range is not provided") val integrator: GaussIntegrator = getIntegrator(range) @@ -87,7 +87,7 @@ public class GaussRuleIntegrator( numPoints: Int = 100, type: GaussRule = GaussRule.LEGANDRE, function: (Double) -> Double, - ): Double = GaussRuleIntegrator(numPoints, type).evaluate( + ): Double = GaussRuleIntegrator(numPoints, type).integrate( UnivariateIntegrand(function, IntegrationRange(range)) ).value!! } diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt index d655b4f61..13a10475f 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt @@ -19,7 +19,7 @@ import kotlin.reflect.KClass public operator fun PointValuePair.component1(): DoubleArray = point public operator fun PointValuePair.component2(): Double = value -public class CMOptimizationProblem(override val symbols: List, ) : +public class CMOptimizationProblem(override val symbols: List) : OptimizationProblem, SymbolIndexer, OptimizationFeature { private val optimizationData: HashMap, OptimizationData> = HashMap() private var optimizatorBuilder: (() -> MultivariateOptimizer)? = null diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt index 671acce07..3693d5796 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt @@ -21,8 +21,8 @@ internal class IntegrationTest { @Test fun customSimpson() { val res = CMIntegrator.simpson().integrate(0.0..PI, function) { - add(CMIntegrator.TargetRelativeAccuracy(1e-4)) - add(CMIntegrator.TargetAbsoluteAccuracy(1e-4)) + targetRelativeAccuracy = 1e-4 + targetAbsoluteAccuracy = 1e-4 } assertTrue { abs(res - 2) < 1e-3 } assertTrue { abs(res - 2) > 1e-12 } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt index 39330e91e..7027e62c7 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt @@ -7,5 +7,5 @@ public interface Integrator { /** * Run one integration pass and return a new [Integrand] with a new set of features */ - public fun evaluate(integrand: I): I + public fun integrate(integrand: I): I } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index ac9c570bc..9389318e8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -39,7 +39,7 @@ public fun UnivariateIntegrator.integrate( range: ClosedRange, vararg features: IntegrandFeature, function: (Double) -> Double, -): Double = evaluate( +): Double = integrate( UnivariateIntegrand(function, IntegrationRange(range), *features) ).value ?: error("Unexpected: no value after integration.") @@ -58,7 +58,7 @@ public fun UnivariateIntegrator.integrate( featureBuilder() add(IntegrationRange(range)) } - return evaluate( + return integrate( UnivariateIntegrand(function, *features.toTypedArray()) ).value ?: error("Unexpected: no value after integration.") } \ No newline at end of file From 05f742452d4ea7c707a9581160aae721d7402dd6 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 16 Mar 2021 20:56:20 +0300 Subject: [PATCH 103/393] Structure naming change --- .github/workflows/publish.yml | 2 +- CHANGELOG.md | 2 + docs/images/KM.svg | 29 +- docs/images/KM_mono.svg | 44 +- docs/images/KMath.svg | 47 +- docs/images/KMath_mono.svg | 239 +++++---- examples/build.gradle.kts | 2 +- .../kmath/benchmarks/NDFieldBenchmark.kt | 12 +- .../kmath/benchmarks/ViktorBenchmark.kt | 12 +- .../kmath/benchmarks/ViktorLogBenchmark.kt | 10 +- .../kmath/commons/fit/fitWithAutoDiff.kt | 4 +- .../kscience/kmath/operations/ComplexDemo.kt | 6 +- .../kscience/kmath/structures/ComplexND.kt | 12 +- .../kscience/kmath/structures/NDField.kt | 22 +- .../kmath/structures/ParallelRealNDField.kt | 60 +-- .../structures/StructureWriteBenchmark.kt | 4 +- .../space/kscience/kmath/ast/MstAlgebra.kt | 2 +- .../estree/TestESTreeOperationsSupport.kt | 4 +- .../kmath/asm/internal/codegenUtils.kt | 2 +- .../kmath/asm/TestAsmOperationsSupport.kt | 4 +- kmath-commons/build.gradle.kts | 2 +- .../kmath/commons/integration/CMIntegrator.kt | 8 +- .../kscience/kmath/commons/linear/CMMatrix.kt | 6 +- .../kscience/kmath/commons/linear/CMSolver.kt | 8 +- .../commons/transform/Transformations.kt | 16 +- .../DerivativeStructureExpressionTest.kt | 4 +- .../{ComplexNDField.kt => ComplexFieldND.kt} | 52 +- .../kscience/kmath/complex/Quaternion.kt | 2 +- kmath-core/api/kmath-core.api | 504 +++++++++--------- .../kmath/linear/BufferedLinearSpace.kt | 2 +- .../kscience/kmath/linear/VirtualMatrix.kt | 6 +- .../kmath/nd/{NDAlgebra.kt => AlgebraND.kt} | 60 +-- ...{BufferNDAlgebra.kt => BufferAlgebraND.kt} | 64 +-- .../nd/{RealNDField.kt => RealFieldND.kt} | 64 +-- .../nd/{ShortNDRing.kt => ShortRingND.kt} | 12 +- .../space/kscience/kmath/nd/Structure1D.kt | 8 +- .../space/kscience/kmath/nd/Structure2D.kt | 12 +- .../nd/{NDStructure.kt => StructureND.kt} | 30 +- .../space/kscience/kmath/operations/BigInt.kt | 8 +- .../kmath/structures/BufferAccessor2D.kt | 4 +- .../space/kscience/kmath/linear/MatrixTest.kt | 6 +- .../kscience/kmath/structures/NDFieldTest.kt | 6 +- .../kmath/structures/NumberNDFieldTest.kt | 8 +- kmath-coroutines/build.gradle.kts | 2 +- .../space/kscience/kmath/chains/Chain.kt | 4 +- .../kmath/coroutines/coroutinesExtra.kt | 6 +- .../kscience/kmath/streaming/RingBuffer.kt | 2 +- ...{LazyNDStructure.kt => LazyStructureND.kt} | 30 +- kmath-dimensions/build.gradle.kts | 2 +- .../kscience/kmath/dimensions/Wrappers.kt | 14 +- kmath-ejml/build.gradle.kts | 2 +- .../space/kscience/kmath/ejml/EjmlMatrix.kt | 6 +- .../kotlin/space/kscience/kmath/real/dot.kt | 2 +- .../kotlin/kaceince/kmath/real/GridTest.kt | 2 +- kmath-functions/build.gradle.kts | 8 +- .../kscience/kmath/integration/Integrand.kt | 1 + .../kscience/kmath/integration/Integrator.kt | 2 +- .../kmath/interpolation/Interpolator.kt | 6 +- .../kmath/interpolation/XYPointSet.kt | 2 +- kmath-geometry/build.gradle.kts | 2 +- .../space/kscience/kmath/histogram/Counter.kt | 3 +- .../kscience/kmath/histogram/Histogram.kt | 2 +- .../kmath/histogram/IndexedHistogramSpace.kt | 8 +- .../kmath/histogram/RealHistogramSpace.kt | 6 +- .../histogram/MultivariateHistogramTest.kt | 2 +- .../kmath/histogram/UnivariateHistogram.kt | 3 +- kmath-kotlingrad/build.gradle.kts | 2 +- kmath-memory/build.gradle.kts | 2 +- .../space/kscience/kmath/memory/MemorySpec.kt | 3 +- .../kscience/kmath/memory/ByteBufferMemory.kt | 5 +- .../kscience/kmath/memory/NativeMemory.kt | 2 +- .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 106 ++-- .../kscience/kmath/nd4j/Nd4jArrayStructure.kt | 4 +- .../kmath/nd4j/Nd4jArrayAlgebraTest.kt | 2 +- .../kmath/nd4j/Nd4jArrayStructureTest.kt | 6 +- kmath-stat/build.gradle.kts | 2 +- .../space/kscience/kmath/stat/Distribution.kt | 2 +- .../kmath/stat/OptimizationProblem.kt | 4 +- .../space/kscience/kmath/stat/RandomChain.kt | 2 +- .../kscience/kmath/stat/distributions.kt | 4 +- kmath-viktor/api/kmath-viktor.api | 148 ++--- kmath-viktor/build.gradle.kts | 2 +- .../kmath/viktor/ViktorNDStructure.kt | 123 ----- .../kmath/viktor/ViktorStructureND.kt | 123 +++++ 84 files changed, 1060 insertions(+), 1010 deletions(-) rename kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/{ComplexNDField.kt => ComplexFieldND.kt} (69%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/{NDAlgebra.kt => AlgebraND.kt} (75%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/{BufferNDAlgebra.kt => BufferAlgebraND.kt} (60%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/{RealNDField.kt => RealFieldND.kt} (61%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/{ShortNDRing.kt => ShortRingND.kt} (80%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/{NDStructure.kt => StructureND.kt} (92%) rename kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/{LazyNDStructure.kt => LazyStructureND.kt} (62%) delete mode 100644 kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt create mode 100644 kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 42fa6d3b6..ca374574e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,7 +12,7 @@ jobs: name: publish strategy: matrix: - os: [macOS-latest, windows-latest] + os: [ macOS-latest, windows-latest ] runs-on: ${{matrix.os}} steps: - name: Checkout the repo diff --git a/CHANGELOG.md b/CHANGELOG.md index eb97698c6..17486bd2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,14 @@ ### Added - ScaleOperations interface - Field extends ScaleOperations +- Basic integration API ### Changed - Exponential operations merged with hyperbolic functions - Space is replaced by Group. Space is reserved for vector spaces. - VectorSpace is now a vector space - Buffer factories for primitives moved to MutableBuffer.Companion +- NDStructure and NDAlgebra to StructureND and AlgebraND respectively ### Deprecated diff --git a/docs/images/KM.svg b/docs/images/KM.svg index 50126cbc5..83af21f35 100644 --- a/docs/images/KM.svg +++ b/docs/images/KM.svg @@ -13,27 +13,30 @@ version="1.1">image/svg+xml + + + image/svg+xml + + image/svg+xml + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + { kotlinOptions.jvmTarget = "11" } -readme{ +readme { maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt index aeee0dafe..e381a1559 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -13,7 +13,7 @@ internal class NDFieldBenchmark { @Benchmark fun autoFieldAdd(blackhole: Blackhole) { with(autoField) { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += one } blackhole.consume(res) } @@ -22,7 +22,7 @@ internal class NDFieldBenchmark { @Benchmark fun specializedFieldAdd(blackhole: Blackhole) { with(specializedField) { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += 1.0 } blackhole.consume(res) } @@ -32,7 +32,7 @@ internal class NDFieldBenchmark { @Benchmark fun boxingFieldAdd(blackhole: Blackhole) { with(genericField) { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += 1.0 } blackhole.consume(res) } @@ -41,8 +41,8 @@ internal class NDFieldBenchmark { private companion object { private const val dim = 1000 private const val n = 100 - private val autoField = NDAlgebra.auto(RealField, dim, dim) - private val specializedField = NDAlgebra.real(dim, dim) - private val genericField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim) + private val autoField = AlgebraND.auto(RealField, dim, dim) + private val specializedField = AlgebraND.real(dim, dim) + private val genericField = AlgebraND.field(RealField, Buffer.Companion::boxing, dim, dim) } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt index c511173a9..21c29affd 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt @@ -5,8 +5,8 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import org.jetbrains.bio.viktor.F64Array -import space.kscience.kmath.nd.NDAlgebra -import space.kscience.kmath.nd.NDStructure +import space.kscience.kmath.nd.AlgebraND +import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.auto import space.kscience.kmath.nd.real import space.kscience.kmath.operations.RealField @@ -17,7 +17,7 @@ internal class ViktorBenchmark { @Benchmark fun automaticFieldAddition(blackhole: Blackhole) { with(autoField) { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += 1.0 } blackhole.consume(res) } @@ -26,7 +26,7 @@ internal class ViktorBenchmark { @Benchmark fun realFieldAddition(blackhole: Blackhole) { with(realField) { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += 1.0 } blackhole.consume(res) } @@ -54,8 +54,8 @@ internal class ViktorBenchmark { private const val n = 100 // automatically build context most suited for given type. - private val autoField = NDAlgebra.auto(RealField, dim, dim) - private val realField = NDAlgebra.real(dim, dim) + private val autoField = AlgebraND.auto(RealField, dim, dim) + private val realField = AlgebraND.real(dim, dim) private val viktorField = ViktorNDField(dim, dim) } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt index 0036b615c..e964f9bff 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt @@ -5,11 +5,11 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import org.jetbrains.bio.viktor.F64Array -import space.kscience.kmath.nd.NDAlgebra +import space.kscience.kmath.nd.AlgebraND import space.kscience.kmath.nd.auto import space.kscience.kmath.nd.real import space.kscience.kmath.operations.RealField -import space.kscience.kmath.viktor.ViktorNDField +import space.kscience.kmath.viktor.ViktorFieldND @State(Scope.Benchmark) internal class ViktorLogBenchmark { @@ -46,8 +46,8 @@ internal class ViktorLogBenchmark { private const val n = 100 // automatically build context most suited for given type. - private val autoField = NDAlgebra.auto(RealField, dim, dim) - private val realNdField = NDAlgebra.real(dim, dim) - private val viktorField = ViktorNDField(intArrayOf(dim, dim)) + private val autoField = AlgebraND.auto(RealField, dim, dim) + private val realNdField = AlgebraND.real(dim, dim) + private val viktorField = ViktorFieldND(intArrayOf(dim, dim)) } } diff --git a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt index 63b819dc9..c26fb34e9 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -90,10 +90,10 @@ fun main() { } } br() - h3{ + h3 { +"Fit result: $result" } - h3{ + h3 { +"Chi2/dof = ${result.value / (x.size - 3)}" } } diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/ComplexDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/ComplexDemo.kt index 5330d9e40..105fb108e 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/operations/ComplexDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/operations/ComplexDemo.kt @@ -2,17 +2,17 @@ package space.kscience.kmath.operations import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.complex -import space.kscience.kmath.nd.NDAlgebra +import space.kscience.kmath.nd.AlgebraND fun main() { // 2d element - val element = NDAlgebra.complex(2, 2).produce { (i, j) -> + val element = AlgebraND.complex(2, 2).produce { (i, j) -> Complex(i.toDouble() - j.toDouble(), i.toDouble() + j.toDouble()) } println(element) // 1d element operation - val result = with(NDAlgebra.complex(8)) { + val result = with(AlgebraND.complex(8)) { val a = produce { (it) -> i * it - it.toDouble() } val b = 3 val c = Complex(1.0, 1.0) diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt index b8cbc9a57..68af2560b 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt @@ -4,8 +4,8 @@ package space.kscience.kmath.structures import space.kscience.kmath.complex.* import space.kscience.kmath.linear.transpose -import space.kscience.kmath.nd.NDAlgebra -import space.kscience.kmath.nd.NDStructure +import space.kscience.kmath.nd.AlgebraND +import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.as2D import space.kscience.kmath.nd.real import space.kscience.kmath.operations.invoke @@ -15,12 +15,12 @@ fun main() { val dim = 1000 val n = 1000 - val realField = NDAlgebra.real(dim, dim) - val complexField: ComplexNDField = NDAlgebra.complex(dim, dim) + val realField = AlgebraND.real(dim, dim) + val complexField: ComplexFieldND = AlgebraND.complex(dim, dim) val realTime = measureTimeMillis { realField { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += 1.0 } @@ -31,7 +31,7 @@ fun main() { val complexTime = measureTimeMillis { complexField { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += 1.0 } diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt index 10fb3cb3d..b884251c4 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt @@ -24,56 +24,56 @@ fun main() { val n = 1000 // automatically build context most suited for given type. - val autoField = NDAlgebra.auto(RealField, dim, dim) + val autoField = AlgebraND.auto(RealField, dim, dim) // specialized nd-field for Double. It works as generic Double field as well - val realField = NDAlgebra.real(dim, dim) + val realField = AlgebraND.real(dim, dim) //A generic boxing field. It should be used for objects, not primitives. - val boxingField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim) + val boxingField = AlgebraND.field(RealField, Buffer.Companion::boxing, dim, dim) // Nd4j specialized field. val nd4jField = Nd4jArrayField.real(dim, dim) //viktor field - val viktorField = ViktorNDField(dim,dim) + val viktorField = ViktorNDField(dim, dim) //parallel processing based on Java Streams - val parallelField = NDAlgebra.realWithStream(dim,dim) + val parallelField = AlgebraND.realWithStream(dim, dim) measureAndPrint("Boxing addition") { boxingField { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += 1.0 } } } measureAndPrint("Specialized addition") { realField { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += 1.0 } } } measureAndPrint("Nd4j specialized addition") { nd4jField { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += 1.0 } } } measureAndPrint("Viktor addition") { viktorField { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += 1.0 } } } measureAndPrint("Parallel stream addition") { parallelField { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += 1.0 } } } measureAndPrint("Automatic field addition") { autoField { - var res: NDStructure = one + var res: StructureND = one repeat(n) { res += 1.0 } } } diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt index 0c914468d..8b3c5dfbb 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt @@ -12,11 +12,11 @@ import java.util.stream.IntStream * A demonstration implementation of NDField over Real using Java [DoubleStream] for parallel execution */ @OptIn(UnstableKMathAPI::class) -class StreamRealNDField( +class StreamRealFieldND( override val shape: IntArray, -) : NDField, - NumbersAddOperations>, - ExtendedField> { +) : FieldND, + NumbersAddOperations>, + ExtendedField> { private val strides = DefaultStrides(shape) override val elementContext: RealField get() = RealField @@ -28,13 +28,13 @@ class StreamRealNDField( return produce { d } } - private val NDStructure.buffer: RealBuffer + private val StructureND.buffer: RealBuffer get() = when { - !shape.contentEquals(this@StreamRealNDField.shape) -> throw ShapeMismatchException( - this@StreamRealNDField.shape, + !shape.contentEquals(this@StreamRealFieldND.shape) -> throw ShapeMismatchException( + this@StreamRealFieldND.shape, shape ) - this is NDBuffer && this.strides == this@StreamRealNDField.strides -> this.buffer as RealBuffer + this is NDBuffer && this.strides == this@StreamRealFieldND.strides -> this.buffer as RealBuffer else -> RealBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } } @@ -48,14 +48,14 @@ class StreamRealNDField( return NDBuffer(strides, array.asBuffer()) } - override fun NDStructure.map( + override fun StructureND.map( transform: RealField.(Double) -> Double, ): NDBuffer { val array = Arrays.stream(buffer.array).parallel().map { RealField.transform(it) }.toArray() return NDBuffer(strides, array.asBuffer()) } - override fun NDStructure.mapIndexed( + override fun StructureND.mapIndexed( transform: RealField.(index: IntArray, Double) -> Double, ): NDBuffer { val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset -> @@ -69,8 +69,8 @@ class StreamRealNDField( } override fun combine( - a: NDStructure, - b: NDStructure, + a: StructureND, + b: StructureND, transform: RealField.(Double, Double) -> Double, ): NDBuffer { val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset -> @@ -79,29 +79,29 @@ class StreamRealNDField( return NDBuffer(strides, array.asBuffer()) } - override fun NDStructure.unaryMinus(): NDStructure = map { -it } + override fun StructureND.unaryMinus(): StructureND = map { -it } - override fun scale(a: NDStructure, value: Double): NDStructure = a.map { it * value } + override fun scale(a: StructureND, value: Double): StructureND = a.map { it * value } - override fun power(arg: NDStructure, pow: Number): NDBuffer = arg.map { power(it, pow) } + override fun power(arg: StructureND, pow: Number): NDBuffer = arg.map { power(it, pow) } - override fun exp(arg: NDStructure): NDBuffer = arg.map { exp(it) } + override fun exp(arg: StructureND): NDBuffer = arg.map { exp(it) } - override fun ln(arg: NDStructure): NDBuffer = arg.map { ln(it) } + override fun ln(arg: StructureND): NDBuffer = arg.map { ln(it) } - override fun sin(arg: NDStructure): NDBuffer = arg.map { sin(it) } - override fun cos(arg: NDStructure): NDBuffer = arg.map { cos(it) } - override fun tan(arg: NDStructure): NDBuffer = arg.map { tan(it) } - override fun asin(arg: NDStructure): NDBuffer = arg.map { asin(it) } - override fun acos(arg: NDStructure): NDBuffer = arg.map { acos(it) } - override fun atan(arg: NDStructure): NDBuffer = arg.map { atan(it) } + override fun sin(arg: StructureND): NDBuffer = arg.map { sin(it) } + override fun cos(arg: StructureND): NDBuffer = arg.map { cos(it) } + override fun tan(arg: StructureND): NDBuffer = arg.map { tan(it) } + override fun asin(arg: StructureND): NDBuffer = arg.map { asin(it) } + override fun acos(arg: StructureND): NDBuffer = arg.map { acos(it) } + override fun atan(arg: StructureND): NDBuffer = arg.map { atan(it) } - override fun sinh(arg: NDStructure): NDBuffer = arg.map { sinh(it) } - override fun cosh(arg: NDStructure): NDBuffer = arg.map { cosh(it) } - override fun tanh(arg: NDStructure): NDBuffer = arg.map { tanh(it) } - override fun asinh(arg: NDStructure): NDBuffer = arg.map { asinh(it) } - override fun acosh(arg: NDStructure): NDBuffer = arg.map { acosh(it) } - override fun atanh(arg: NDStructure): NDBuffer = arg.map { atanh(it) } + override fun sinh(arg: StructureND): NDBuffer = arg.map { sinh(it) } + override fun cosh(arg: StructureND): NDBuffer = arg.map { cosh(it) } + override fun tanh(arg: StructureND): NDBuffer = arg.map { tanh(it) } + override fun asinh(arg: StructureND): NDBuffer = arg.map { asinh(it) } + override fun acosh(arg: StructureND): NDBuffer = arg.map { acosh(it) } + override fun atanh(arg: StructureND): NDBuffer = arg.map { atanh(it) } } -fun NDAlgebra.Companion.realWithStream(vararg shape: Int): StreamRealNDField = StreamRealNDField(shape) \ No newline at end of file +fun AlgebraND.Companion.realWithStream(vararg shape: Int): StreamRealFieldND = StreamRealFieldND(shape) \ No newline at end of file diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt index 66d85edff..7aa5a07fd 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt @@ -1,13 +1,13 @@ package space.kscience.kmath.structures -import space.kscience.kmath.nd.NDStructure +import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.mapToBuffer import kotlin.system.measureTimeMillis @Suppress("UNUSED_VARIABLE") fun main() { val n = 6000 - val structure = NDStructure.buffered(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 } + val structure = StructureND.buffered(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 } structure.mapToBuffer { it + 1 } // warm-up val time1 = measureTimeMillis { val res = structure.mapToBuffer { it + 1 } } println("Structure mapping finished in $time1 millis") diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt index 5ed39687b..c1aeae90e 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt @@ -50,7 +50,7 @@ public object MstGroup : Group, NumericAlgebra, ScaleOperations { */ @OptIn(UnstableKMathAPI::class) public object MstRing : Ring, NumbersAddOperations, ScaleOperations { - public override val zero: MST.Numeric get() = MstGroup.zero + public override val zero: MST.Numeric get() = MstGroup.zero public override val one: MST.Numeric = number(1.0) public override fun number(value: Number): MST.Numeric = MstGroup.number(value) diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt index 27bf2f167..590d0957d 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt @@ -32,7 +32,9 @@ internal class TestESTreeOperationsSupport { @Test fun testMultipleCalls() { - val e = RealField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) }.compile() + val e = + RealField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } + .compile() val r = Random(0) var s = 0.0 repeat(1000000) { s += e("x" to r.nextDouble()) } diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt index 1124a860f..4522c966f 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt @@ -86,7 +86,7 @@ internal inline fun ClassWriter.visitField( descriptor: String, signature: String?, value: Any?, - block: FieldVisitor.() -> Unit + block: FieldVisitor.() -> Unit, ): FieldVisitor { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return visitField(access, name, descriptor, signature, value).apply(block) diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt index e99075f07..7047c824c 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt @@ -32,7 +32,9 @@ internal class TestAsmOperationsSupport { @Test fun testMultipleCalls() { - val e = RealField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) }.compile() + val e = + RealField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } + .compile() val r = Random(0) var s = 0.0 repeat(1000000) { s += e("x" to r.nextDouble()) } diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index 4fe16605a..56dcef29a 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -12,6 +12,6 @@ dependencies { api("org.apache.commons:commons-math3:3.6.1") } -readme{ +readme { maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt index 8511ed66e..e1ba7d777 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt @@ -80,13 +80,13 @@ public class CMIntegrator( @UnstableKMathAPI public var MutableList.targetAbsoluteAccuracy: Double? get() = filterIsInstance().lastOrNull()?.value - set(value){ - value?.let { add(CMIntegrator.TargetAbsoluteAccuracy(value))} + set(value) { + value?.let { add(CMIntegrator.TargetAbsoluteAccuracy(value)) } } @UnstableKMathAPI public var MutableList.targetRelativeAccuracy: Double? get() = filterIsInstance().lastOrNull()?.value - set(value){ - value?.let { add(CMIntegrator.TargetRelativeAccuracy(value))} + set(value) { + value?.let { add(CMIntegrator.TargetRelativeAccuracy(value)) } } \ No newline at end of file diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index 4671598f7..4e3a44a83 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -3,7 +3,7 @@ package space.kscience.kmath.commons.linear import org.apache.commons.math3.linear.* import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.NDStructure +import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.RealField import space.kscience.kmath.structures.RealBuffer import kotlin.reflect.KClass @@ -17,8 +17,8 @@ public class CMMatrix(public val origin: RealMatrix) : Matrix { override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is NDStructure<*>) return false - return NDStructure.contentEquals(this, other) + if (other !is StructureND<*>) return false + return StructureND.contentEquals(this, other) } override fun hashCode(): Int = origin.hashCode() diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt index b5fd0154e..b4706473a 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt @@ -14,7 +14,7 @@ public enum class CMDecomposition { public fun CMLinearSpace.solver( a: Matrix, - decomposition: CMDecomposition = CMDecomposition.LUP + decomposition: CMDecomposition = CMDecomposition.LUP, ): DecompositionSolver = when (decomposition) { CMDecomposition.LUP -> LUDecomposition(a.toCM().origin).solver CMDecomposition.RRQR -> RRQRDecomposition(a.toCM().origin).solver @@ -26,16 +26,16 @@ public fun CMLinearSpace.solver( public fun CMLinearSpace.solve( a: Matrix, b: Matrix, - decomposition: CMDecomposition = CMDecomposition.LUP + decomposition: CMDecomposition = CMDecomposition.LUP, ): CMMatrix = solver(a, decomposition).solve(b.toCM().origin).wrap() public fun CMLinearSpace.solve( a: Matrix, b: Point, - decomposition: CMDecomposition = CMDecomposition.LUP + decomposition: CMDecomposition = CMDecomposition.LUP, ): CMVector = solver(a, decomposition).solve(b.toCM().origin).toPoint() public fun CMLinearSpace.inverse( a: Matrix, - decomposition: CMDecomposition = CMDecomposition.LUP + decomposition: CMDecomposition = CMDecomposition.LUP, ): CMMatrix = solver(a, decomposition).inverse.wrap() diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt index e174a237f..aaee594ad 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt @@ -33,34 +33,34 @@ public object Transformations { public fun fourier( normalization: DftNormalization = DftNormalization.STANDARD, - direction: TransformType = TransformType.FORWARD + direction: TransformType = TransformType.FORWARD, ): SuspendBufferTransform = { FastFourierTransformer(normalization).transform(it.toArray(), direction).asBuffer() } public fun realFourier( normalization: DftNormalization = DftNormalization.STANDARD, - direction: TransformType = TransformType.FORWARD + direction: TransformType = TransformType.FORWARD, ): SuspendBufferTransform = { FastFourierTransformer(normalization).transform(it.asArray(), direction).asBuffer() } public fun sine( normalization: DstNormalization = DstNormalization.STANDARD_DST_I, - direction: TransformType = TransformType.FORWARD + direction: TransformType = TransformType.FORWARD, ): SuspendBufferTransform = { FastSineTransformer(normalization).transform(it.asArray(), direction).asBuffer() } public fun cosine( normalization: DctNormalization = DctNormalization.STANDARD_DCT_I, - direction: TransformType = TransformType.FORWARD + direction: TransformType = TransformType.FORWARD, ): SuspendBufferTransform = { FastCosineTransformer(normalization).transform(it.asArray(), direction).asBuffer() } public fun hadamard( - direction: TransformType = TransformType.FORWARD + direction: TransformType = TransformType.FORWARD, ): SuspendBufferTransform = { FastHadamardTransformer().transform(it.asArray(), direction).asBuffer() } @@ -72,7 +72,7 @@ public object Transformations { @FlowPreview public fun Flow>.FFT( normalization: DftNormalization = DftNormalization.STANDARD, - direction: TransformType = TransformType.FORWARD + direction: TransformType = TransformType.FORWARD, ): Flow> { val transform = Transformations.fourier(normalization, direction) return map { transform(it) } @@ -82,7 +82,7 @@ public fun Flow>.FFT( @JvmName("realFFT") public fun Flow>.FFT( normalization: DftNormalization = DftNormalization.STANDARD, - direction: TransformType = TransformType.FORWARD + direction: TransformType = TransformType.FORWARD, ): Flow> { val transform = Transformations.realFourier(normalization, direction) return map(transform) @@ -96,7 +96,7 @@ public fun Flow>.FFT( public fun Flow.FFT( bufferSize: Int = Int.MAX_VALUE, normalization: DftNormalization = DftNormalization.STANDARD, - direction: TransformType = TransformType.FORWARD + direction: TransformType = TransformType.FORWARD, ): Flow = chunked(bufferSize).FFT(normalization, direction).spread() /** diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt index 19b6e28da..8d9bab652 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt @@ -27,10 +27,10 @@ internal class AutoDiffTest { val y = bindSymbol("y") val z = x * (-sin(x * y) + y) + 2.0 println(z.derivative(x)) - println(z.derivative(y,x)) + println(z.derivative(y, x)) assertEquals(z.derivative(x, y), z.derivative(y, x)) //check that improper order cause failure - assertFails { z.derivative(x,x,y) } + assertFails { z.derivative(x, x, y) } } } diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt similarity index 69% rename from kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt rename to kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt index 382659e10..382410e45 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt @@ -1,10 +1,10 @@ package space.kscience.kmath.complex import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.BufferedNDField -import space.kscience.kmath.nd.NDAlgebra +import space.kscience.kmath.nd.AlgebraND +import space.kscience.kmath.nd.BufferedFieldND import space.kscience.kmath.nd.NDBuffer -import space.kscience.kmath.nd.NDStructure +import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.NumbersAddOperations import space.kscience.kmath.structures.Buffer @@ -16,11 +16,11 @@ import kotlin.contracts.contract * An optimized nd-field for complex numbers */ @OptIn(UnstableKMathAPI::class) -public class ComplexNDField( +public class ComplexFieldND( shape: IntArray, -) : BufferedNDField(shape, ComplexField, Buffer.Companion::complex), - NumbersAddOperations>, - ExtendedField> { +) : BufferedFieldND(shape, ComplexField, Buffer.Companion::complex), + NumbersAddOperations>, + ExtendedField> { override val zero: NDBuffer by lazy { produce { zero } } override val one: NDBuffer by lazy { produce { one } } @@ -76,44 +76,44 @@ public class ComplexNDField( // return BufferedNDFieldElement(this, buffer) // } - override fun power(arg: NDStructure, pow: Number): NDBuffer = arg.map { power(it, pow) } + override fun power(arg: StructureND, pow: Number): NDBuffer = arg.map { power(it, pow) } - override fun exp(arg: NDStructure): NDBuffer = arg.map { exp(it) } + override fun exp(arg: StructureND): NDBuffer = arg.map { exp(it) } - override fun ln(arg: NDStructure): NDBuffer = arg.map { ln(it) } + override fun ln(arg: StructureND): NDBuffer = arg.map { ln(it) } - override fun sin(arg: NDStructure): NDBuffer = arg.map { sin(it) } - override fun cos(arg: NDStructure): NDBuffer = arg.map { cos(it) } - override fun tan(arg: NDStructure): NDBuffer = arg.map { tan(it) } - override fun asin(arg: NDStructure): NDBuffer = arg.map { asin(it) } - override fun acos(arg: NDStructure): NDBuffer = arg.map { acos(it) } - override fun atan(arg: NDStructure): NDBuffer = arg.map { atan(it) } + override fun sin(arg: StructureND): NDBuffer = arg.map { sin(it) } + override fun cos(arg: StructureND): NDBuffer = arg.map { cos(it) } + override fun tan(arg: StructureND): NDBuffer = arg.map { tan(it) } + override fun asin(arg: StructureND): NDBuffer = arg.map { asin(it) } + override fun acos(arg: StructureND): NDBuffer = arg.map { acos(it) } + override fun atan(arg: StructureND): NDBuffer = arg.map { atan(it) } - override fun sinh(arg: NDStructure): NDBuffer = arg.map { sinh(it) } - override fun cosh(arg: NDStructure): NDBuffer = arg.map { cosh(it) } - override fun tanh(arg: NDStructure): NDBuffer = arg.map { tanh(it) } - override fun asinh(arg: NDStructure): NDBuffer = arg.map { asinh(it) } - override fun acosh(arg: NDStructure): NDBuffer = arg.map { acosh(it) } - override fun atanh(arg: NDStructure): NDBuffer = arg.map { atanh(it) } + override fun sinh(arg: StructureND): NDBuffer = arg.map { sinh(it) } + override fun cosh(arg: StructureND): NDBuffer = arg.map { cosh(it) } + override fun tanh(arg: StructureND): NDBuffer = arg.map { tanh(it) } + override fun asinh(arg: StructureND): NDBuffer = arg.map { asinh(it) } + override fun acosh(arg: StructureND): NDBuffer = arg.map { acosh(it) } + override fun atanh(arg: StructureND): NDBuffer = arg.map { atanh(it) } } /** * Fast element production using function inlining */ -public inline fun BufferedNDField.produceInline(initializer: ComplexField.(Int) -> Complex): NDBuffer { +public inline fun BufferedFieldND.produceInline(initializer: ComplexField.(Int) -> Complex): NDBuffer { contract { callsInPlace(initializer, InvocationKind.EXACTLY_ONCE) } val buffer = Buffer.complex(strides.linearSize) { offset -> ComplexField.initializer(offset) } return NDBuffer(strides, buffer) } -public fun NDAlgebra.Companion.complex(vararg shape: Int): ComplexNDField = ComplexNDField(shape) +public fun AlgebraND.Companion.complex(vararg shape: Int): ComplexFieldND = ComplexFieldND(shape) /** * Produce a context for n-dimensional operations inside this real field */ -public inline fun ComplexField.nd(vararg shape: Int, action: ComplexNDField.() -> R): R { +public inline fun ComplexField.nd(vararg shape: Int, action: ComplexFieldND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return ComplexNDField(shape).action() + return ComplexFieldND(shape).action() } diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index d391aff18..9a0346ca7 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -172,7 +172,7 @@ public object QuaternionField : Field, Norm, else -> super.bindSymbol(value) } - override fun number(value: Number): Quaternion =value.toQuaternion() + override fun number(value: Number): Quaternion = value.toQuaternion() public override fun sinh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / 2.0 public override fun cosh(arg: Quaternion): Quaternion = (exp(arg) + exp(-arg)) / 2.0 diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index c5e13fe20..2fb28d73a 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -679,73 +679,91 @@ public final class space/kscience/kmath/misc/CumulativeKt { public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation { } -public abstract interface class space/kscience/kmath/nd/BufferNDAlgebra : space/kscience/kmath/nd/NDAlgebra { - public abstract fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; - public abstract fun getBuffer (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/structures/Buffer; +public abstract interface class space/kscience/kmath/nd/AlgebraND { + public static final field Companion Lspace/kscience/kmath/nd/AlgebraND$Companion; + public abstract fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; + public abstract fun getShape ()[I + public abstract fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; +} + +public final class space/kscience/kmath/nd/AlgebraND$Companion { +} + +public final class space/kscience/kmath/nd/AlgebraND$DefaultImpls { + public static fun invoke (Lspace/kscience/kmath/nd/AlgebraND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; +} + +public abstract interface class space/kscience/kmath/nd/BufferAlgebraND : space/kscience/kmath/nd/AlgebraND { + public abstract fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public abstract fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; public abstract fun getBufferFactory ()Lkotlin/jvm/functions/Function2; public abstract fun getStrides ()Lspace/kscience/kmath/nd/Strides; - public abstract fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; - public abstract fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public abstract fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public abstract fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; } -public final class space/kscience/kmath/nd/BufferNDAlgebra$DefaultImpls { - public static fun combine (Lspace/kscience/kmath/nd/BufferNDAlgebra;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; - public static fun getBuffer (Lspace/kscience/kmath/nd/BufferNDAlgebra;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/structures/Buffer; - public static fun invoke (Lspace/kscience/kmath/nd/BufferNDAlgebra;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun map (Lspace/kscience/kmath/nd/BufferNDAlgebra;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; - public static fun mapIndexed (Lspace/kscience/kmath/nd/BufferNDAlgebra;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; - public static fun produce (Lspace/kscience/kmath/nd/BufferNDAlgebra;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; +public final class space/kscience/kmath/nd/BufferAlgebraND$DefaultImpls { + public static fun combine (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public static fun getBuffer (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; + public static fun invoke (Lspace/kscience/kmath/nd/BufferAlgebraND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun map (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public static fun mapIndexed (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public static fun produce (Lspace/kscience/kmath/nd/BufferAlgebraND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; } -public final class space/kscience/kmath/nd/BufferNDAlgebraKt { - public static final fun field (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDField; - public static final fun group (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDGroup; +public final class space/kscience/kmath/nd/BufferAlgebraNDKt { + public static final fun field (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedFieldND; + public static final fun group (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedGroupND; public static final fun ndField (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun ndGroup (Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun ndRing (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun ring (Lspace/kscience/kmath/nd/NDAlgebra$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedNDRing; + public static final fun ring (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedRingND; } -public class space/kscience/kmath/nd/BufferedNDField : space/kscience/kmath/nd/BufferedNDRing, space/kscience/kmath/nd/NDField { +public class space/kscience/kmath/nd/BufferedFieldND : space/kscience/kmath/nd/BufferedRingND, space/kscience/kmath/nd/FieldND { public fun ([ILspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;)V public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; - public fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public fun div (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; + public fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public fun div (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun divide (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun divide (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; - public fun scale (Lspace/kscience/kmath/nd/NDStructure;D)Lspace/kscience/kmath/nd/NDStructure; + public fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; } -public class space/kscience/kmath/nd/BufferedNDGroup : space/kscience/kmath/nd/BufferNDAlgebra, space/kscience/kmath/nd/NDGroup { +public class space/kscience/kmath/nd/BufferedGroupND : space/kscience/kmath/nd/BufferAlgebraND, space/kscience/kmath/nd/GroupND { public fun ([ILspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;)V public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun add (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun add (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure; - public fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure; - public fun getBuffer (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/structures/Buffer; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; + public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; + public fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; public final fun getBufferFactory ()Lkotlin/jvm/functions/Function2; public synthetic fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; public final fun getElementContext ()Lspace/kscience/kmath/operations/Group; @@ -753,41 +771,41 @@ public class space/kscience/kmath/nd/BufferedNDGroup : space/kscience/kmath/nd/B public fun getStrides ()Lspace/kscience/kmath/nd/Strides; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer; - public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure; - public fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure; + public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; + public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public fun minus (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public fun minus (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public fun plus (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public fun plus (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure; + public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryMinus (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun unaryMinus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun unaryPlus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } -public class space/kscience/kmath/nd/BufferedNDRing : space/kscience/kmath/nd/BufferedNDGroup, space/kscience/kmath/nd/NDRing { +public class space/kscience/kmath/nd/BufferedRingND : space/kscience/kmath/nd/BufferedGroupND, space/kscience/kmath/nd/RingND { public fun ([ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun multiply (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public fun times (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public fun times (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath/nd/Strides { @@ -807,6 +825,74 @@ public final class space/kscience/kmath/nd/DefaultStrides$Companion { public final fun invoke ([I)Lspace/kscience/kmath/nd/Strides; } +public abstract interface class space/kscience/kmath/nd/FieldND : space/kscience/kmath/nd/RingND, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/ScaleOperations { + public abstract fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun divide (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; +} + +public final class space/kscience/kmath/nd/FieldND$DefaultImpls { + public static fun add (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun binaryOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public static fun bindSymbol (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; + public static fun div (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun div (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; + public static fun div (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public static fun div (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun divide (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun invoke (Lspace/kscience/kmath/nd/FieldND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun leftSideNumberOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public static fun minus (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun minus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public static fun minus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun multiply (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun number (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; + public static fun plus (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun plus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public static fun plus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun rightSideNumberOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; + public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public static fun times (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun times (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun times (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; + public static fun times (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public static fun times (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun unaryOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public static fun unaryPlus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; +} + +public abstract interface class space/kscience/kmath/nd/GroupND : space/kscience/kmath/nd/AlgebraND, space/kscience/kmath/operations/Group { + public static final field Companion Lspace/kscience/kmath/nd/GroupND$Companion; + public abstract fun add (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; +} + +public final class space/kscience/kmath/nd/GroupND$Companion { +} + +public final class space/kscience/kmath/nd/GroupND$DefaultImpls { + public static fun add (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun binaryOperation (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public static fun bindSymbol (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; + public static fun invoke (Lspace/kscience/kmath/nd/GroupND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun minus (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun minus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public static fun minus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun plus (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun plus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public static fun plus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun unaryOperation (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public static fun unaryPlus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; +} + public final class space/kscience/kmath/nd/MutableNDBuffer : space/kscience/kmath/nd/NDBuffer, space/kscience/kmath/nd/MutableNDStructure { public fun (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/MutableBuffer;)V public synthetic fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; @@ -814,7 +900,7 @@ public final class space/kscience/kmath/nd/MutableNDBuffer : space/kscience/kmat public fun set ([ILjava/lang/Object;)V } -public abstract interface class space/kscience/kmath/nd/MutableNDStructure : space/kscience/kmath/nd/NDStructure { +public abstract interface class space/kscience/kmath/nd/MutableNDStructure : space/kscience/kmath/nd/StructureND { public abstract fun set ([ILjava/lang/Object;)V } @@ -822,25 +908,7 @@ public final class space/kscience/kmath/nd/MutableNDStructure$DefaultImpls { public static fun getDimension (Lspace/kscience/kmath/nd/MutableNDStructure;)I } -public abstract interface class space/kscience/kmath/nd/NDAlgebra { - public static final field Companion Lspace/kscience/kmath/nd/NDAlgebra$Companion; - public abstract fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; - public abstract fun getShape ()[I - public abstract fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure; -} - -public final class space/kscience/kmath/nd/NDAlgebra$Companion { -} - -public final class space/kscience/kmath/nd/NDAlgebra$DefaultImpls { - public static fun invoke (Lspace/kscience/kmath/nd/NDAlgebra;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; -} - -public class space/kscience/kmath/nd/NDBuffer : space/kscience/kmath/nd/NDStructure { +public class space/kscience/kmath/nd/NDBuffer : space/kscience/kmath/nd/StructureND { public fun (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/Buffer;)V public fun elements ()Lkotlin/sequences/Sequence; public fun equals (Ljava/lang/Object;)Z @@ -853,204 +921,107 @@ public class space/kscience/kmath/nd/NDBuffer : space/kscience/kmath/nd/NDStruct public fun toString ()Ljava/lang/String; } -public abstract interface class space/kscience/kmath/nd/NDField : space/kscience/kmath/nd/NDRing, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/ScaleOperations { - public abstract fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun divide (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; -} - -public final class space/kscience/kmath/nd/NDField$DefaultImpls { - public static fun add (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun binaryOperation (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure; - public static fun div (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun div (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; - public static fun div (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public static fun div (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun divide (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun invoke (Lspace/kscience/kmath/nd/NDField;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun leftSideNumberOperation (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun minus (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun minus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public static fun minus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun multiply (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun number (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; - public static fun plus (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun plus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public static fun plus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun rightSideNumberOperation (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; - public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun times (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun times (Lspace/kscience/kmath/nd/NDField;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun times (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; - public static fun times (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public static fun times (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun unaryOperation (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/NDField;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/nd/NDField;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; -} - -public abstract interface class space/kscience/kmath/nd/NDGroup : space/kscience/kmath/nd/NDAlgebra, space/kscience/kmath/operations/Group { - public static final field Companion Lspace/kscience/kmath/nd/NDGroup$Companion; - public abstract fun add (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; -} - -public final class space/kscience/kmath/nd/NDGroup$Companion { -} - -public final class space/kscience/kmath/nd/NDGroup$DefaultImpls { - public static fun add (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun binaryOperation (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure; - public static fun invoke (Lspace/kscience/kmath/nd/NDGroup;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun minus (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun minus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public static fun minus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun plus (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun plus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public static fun plus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun unaryOperation (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/NDGroup;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/nd/NDGroup;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; -} - -public abstract interface class space/kscience/kmath/nd/NDRing : space/kscience/kmath/nd/NDGroup, space/kscience/kmath/operations/Ring { - public static final field Companion Lspace/kscience/kmath/nd/NDRing$Companion; - public abstract fun multiply (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public abstract fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; -} - -public final class space/kscience/kmath/nd/NDRing$Companion { -} - -public final class space/kscience/kmath/nd/NDRing$DefaultImpls { - public static fun add (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun binaryOperation (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure; - public static fun invoke (Lspace/kscience/kmath/nd/NDRing;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun minus (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun minus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public static fun minus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun multiply (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun plus (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun plus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public static fun plus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun times (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun times (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public static fun times (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun unaryOperation (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/NDRing;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/nd/NDRing;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; -} - -public abstract interface class space/kscience/kmath/nd/NDStructure { - public static final field Companion Lspace/kscience/kmath/nd/NDStructure$Companion; - public abstract fun elements ()Lkotlin/sequences/Sequence; - public abstract fun equals (Ljava/lang/Object;)Z - public abstract fun get ([I)Ljava/lang/Object; - public abstract fun getDimension ()I - public abstract fun getShape ()[I - public abstract fun hashCode ()I -} - -public final class space/kscience/kmath/nd/NDStructure$Companion { - public final fun auto (Lkotlin/reflect/KClass;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; - public final fun auto (Lkotlin/reflect/KClass;[ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; - public final fun buffered (Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; - public final fun buffered ([ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; - public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/NDStructure$Companion;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer; - public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/NDStructure$Companion;[ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer; - public final fun contentEquals (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Z -} - -public final class space/kscience/kmath/nd/NDStructure$DefaultImpls { - public static fun getDimension (Lspace/kscience/kmath/nd/NDStructure;)I -} - -public final class space/kscience/kmath/nd/NDStructureKt { - public static final fun get (Lspace/kscience/kmath/nd/NDStructure;[I)Ljava/lang/Object; - public static final fun mapInPlace (Lspace/kscience/kmath/nd/MutableNDStructure;Lkotlin/jvm/functions/Function2;)V -} - -public final class space/kscience/kmath/nd/RealNDField : space/kscience/kmath/nd/BufferedNDField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { +public final class space/kscience/kmath/nd/RealFieldND : space/kscience/kmath/nd/BufferedFieldND, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { public fun ([I)V public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; - public fun acos (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; + public fun acos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun acosh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; + public fun acosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; - public fun asin (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; + public fun asin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun asinh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; + public fun asinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; - public fun atan (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; + public fun atan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun atanh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; - public fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure; + public fun atanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; - public fun cos (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; + public fun cos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun cosh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; + public fun cosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; - public fun exp (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun getBuffer (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/structures/Buffer; - public fun getBuffer-LGjt3BI (Lspace/kscience/kmath/nd/NDStructure;)[D + public fun exp (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; + public fun getBuffer-LGjt3BI (Lspace/kscience/kmath/nd/StructureND;)[D public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; - public fun ln (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; - public fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure; - public fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure; + public fun ln (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; + public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public synthetic fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public fun pow (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun power (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; + public fun power (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure; + public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; - public fun scale (Lspace/kscience/kmath/nd/NDStructure;D)Lspace/kscience/kmath/nd/NDStructure; + public fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; - public fun sin (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; + public fun sin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun sinh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; + public fun sinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun sqrt (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; - public fun tan (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; + public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun tanh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDBuffer; + public fun tanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } -public final class space/kscience/kmath/nd/RealNDFieldKt { +public final class space/kscience/kmath/nd/RealFieldNDKt { public static final fun nd (Lspace/kscience/kmath/operations/RealField;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun real (Lspace/kscience/kmath/nd/NDAlgebra$Companion;[I)Lspace/kscience/kmath/nd/RealNDField; + public static final fun real (Lspace/kscience/kmath/nd/AlgebraND$Companion;[I)Lspace/kscience/kmath/nd/RealFieldND; +} + +public abstract interface class space/kscience/kmath/nd/RingND : space/kscience/kmath/nd/GroupND, space/kscience/kmath/operations/Ring { + public static final field Companion Lspace/kscience/kmath/nd/RingND$Companion; + public abstract fun multiply (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; +} + +public final class space/kscience/kmath/nd/RingND$Companion { +} + +public final class space/kscience/kmath/nd/RingND$DefaultImpls { + public static fun add (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun binaryOperation (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public static fun bindSymbol (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; + public static fun invoke (Lspace/kscience/kmath/nd/RingND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun minus (Lspace/kscience/kmath/nd/RingND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun minus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public static fun minus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun multiply (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun plus (Lspace/kscience/kmath/nd/RingND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun plus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public static fun plus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun times (Lspace/kscience/kmath/nd/RingND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun times (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public static fun times (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun unaryOperation (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public static fun unaryPlus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } public final class space/kscience/kmath/nd/ShapeMismatchException : java/lang/RuntimeException { @@ -1059,33 +1030,33 @@ public final class space/kscience/kmath/nd/ShapeMismatchException : java/lang/Ru public final fun getExpected ()[I } -public final class space/kscience/kmath/nd/ShortNDRing : space/kscience/kmath/nd/BufferedNDRing, space/kscience/kmath/operations/NumbersAddOperations { +public final class space/kscience/kmath/nd/ShortRingND : space/kscience/kmath/nd/BufferedRingND, space/kscience/kmath/operations/NumbersAddOperations { public fun ([I)V public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; } -public final class space/kscience/kmath/nd/ShortNDRingKt { +public final class space/kscience/kmath/nd/ShortRingNDKt { public static final fun nd (Lspace/kscience/kmath/operations/ShortRing;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun produceInline (Lspace/kscience/kmath/nd/BufferedNDRing;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public static final fun produceInline (Lspace/kscience/kmath/nd/BufferedRingND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; } public abstract interface class space/kscience/kmath/nd/Strides { @@ -1101,7 +1072,7 @@ public final class space/kscience/kmath/nd/Strides$DefaultImpls { public static fun indices (Lspace/kscience/kmath/nd/Strides;)Lkotlin/sequences/Sequence; } -public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/NDStructure, space/kscience/kmath/structures/Buffer { +public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/StructureND, space/kscience/kmath/structures/Buffer { public abstract fun get ([I)Ljava/lang/Object; public abstract fun getDimension ()I public abstract fun iterator ()Ljava/util/Iterator; @@ -1115,11 +1086,11 @@ public final class space/kscience/kmath/nd/Structure1D$DefaultImpls { } public final class space/kscience/kmath/nd/Structure1DKt { - public static final fun as1D (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/Structure1D; + public static final fun as1D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure1D; public static final fun asND (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/nd/Structure1D; } -public abstract interface class space/kscience/kmath/nd/Structure2D : space/kscience/kmath/nd/NDStructure { +public abstract interface class space/kscience/kmath/nd/Structure2D : space/kscience/kmath/nd/StructureND { public static final field Companion Lspace/kscience/kmath/nd/Structure2D$Companion; public abstract fun elements ()Lkotlin/sequences/Sequence; public abstract fun get (II)Ljava/lang/Object; @@ -1144,7 +1115,36 @@ public final class space/kscience/kmath/nd/Structure2D$DefaultImpls { } public final class space/kscience/kmath/nd/Structure2DKt { - public static final fun as2D (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/Structure2D; + public static final fun as2D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure2D; +} + +public abstract interface class space/kscience/kmath/nd/StructureND { + public static final field Companion Lspace/kscience/kmath/nd/StructureND$Companion; + public abstract fun elements ()Lkotlin/sequences/Sequence; + public abstract fun equals (Ljava/lang/Object;)Z + public abstract fun get ([I)Ljava/lang/Object; + public abstract fun getDimension ()I + public abstract fun getShape ()[I + public abstract fun hashCode ()I +} + +public final class space/kscience/kmath/nd/StructureND$Companion { + public final fun auto (Lkotlin/reflect/KClass;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; + public final fun auto (Lkotlin/reflect/KClass;[ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; + public final fun buffered (Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; + public final fun buffered ([ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; + public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer; + public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;[ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer; + public final fun contentEquals (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Z +} + +public final class space/kscience/kmath/nd/StructureND$DefaultImpls { + public static fun getDimension (Lspace/kscience/kmath/nd/StructureND;)I +} + +public final class space/kscience/kmath/nd/StructureNDKt { + public static final fun get (Lspace/kscience/kmath/nd/StructureND;[I)Ljava/lang/Object; + public static final fun mapInPlace (Lspace/kscience/kmath/nd/MutableNDStructure;Lkotlin/jvm/functions/Function2;)V } public abstract interface class space/kscience/kmath/operations/Algebra { @@ -1287,7 +1287,7 @@ public final class space/kscience/kmath/operations/BigIntField : space/kscience/ public final class space/kscience/kmath/operations/BigIntKt { public static final fun abs (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; - public static final fun bigInt (Lspace/kscience/kmath/nd/NDAlgebra$Companion;[I)Lspace/kscience/kmath/nd/BufferedNDRing; + public static final fun bigInt (Lspace/kscience/kmath/nd/AlgebraND$Companion;[I)Lspace/kscience/kmath/nd/BufferedRingND; public static final fun bigInt (Lspace/kscience/kmath/structures/Buffer$Companion;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; public static final fun bigInt (Lspace/kscience/kmath/structures/MutableBuffer$Companion;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableBuffer; public static final fun parseBigInteger (Ljava/lang/String;)Lspace/kscience/kmath/operations/BigInt; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt index fe92a711a..662cd6409 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt @@ -17,7 +17,7 @@ public class BufferedLinearSpace>( private fun ndRing( rows: Int, cols: Int, - ): BufferedNDRing = NDAlgebra.ring(elementAlgebra, bufferFactory, rows, cols) + ): BufferedRingND = AlgebraND.ring(elementAlgebra, bufferFactory, rows, cols) override fun buildMatrix(rows: Int, columns: Int, initializer: A.(i: Int, j: Int) -> T): Matrix = ndRing(rows, columns).produce { (i, j) -> elementAlgebra.initializer(i, j) }.as2D() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt index 8efa08f81..56cafbdb5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.linear -import space.kscience.kmath.nd.NDStructure +import space.kscience.kmath.nd.StructureND /** * The matrix where each element is evaluated each time when is being accessed. @@ -19,8 +19,8 @@ public class VirtualMatrix( override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is NDStructure<*>) return false - return NDStructure.contentEquals(this, other) + if (other !is StructureND<*>) return false + return StructureND.contentEquals(this, other) } override fun hashCode(): Int { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt similarity index 75% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt index 5514a8f0f..b23ce947d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt @@ -21,7 +21,7 @@ public class ShapeMismatchException(public val expected: IntArray, public val ac * @param C the type of the element context. * @param N the type of the structure. */ -public interface NDAlgebra> { +public interface AlgebraND> { /** * The shape of ND-structures this algebra operates on. */ @@ -35,27 +35,27 @@ public interface NDAlgebra> { /** * Produces a new NDStructure using given initializer function. */ - public fun produce(initializer: C.(IntArray) -> T): NDStructure + public fun produce(initializer: C.(IntArray) -> T): StructureND /** * Maps elements from one structure to another one by applying [transform] to them. */ - public fun NDStructure.map(transform: C.(T) -> T): NDStructure + public fun StructureND.map(transform: C.(T) -> T): StructureND /** * Maps elements from one structure to another one by applying [transform] to them alongside with their indices. */ - public fun NDStructure.mapIndexed(transform: C.(index: IntArray, T) -> T): NDStructure + public fun StructureND.mapIndexed(transform: C.(index: IntArray, T) -> T): StructureND /** * Combines two structures into one. */ - public fun combine(a: NDStructure, b: NDStructure, transform: C.(T, T) -> T): NDStructure + public fun combine(a: StructureND, b: StructureND, transform: C.(T, T) -> T): StructureND /** - * Element-wise invocation of function working on [T] on a [NDStructure]. + * Element-wise invocation of function working on [T] on a [StructureND]. */ - public operator fun Function1.invoke(structure: NDStructure): NDStructure = + public operator fun Function1.invoke(structure: StructureND): StructureND = structure.map { value -> this@invoke(value) } /** @@ -67,7 +67,7 @@ public interface NDAlgebra> { * @return a feature object or `null` if it isn't present. */ @UnstableKMathAPI - public fun getFeature(structure: NDStructure, type: KClass): F? = structure.getFeature(type) + public fun getFeature(structure: StructureND, type: KClass): F? = structure.getFeature(type) public companion object } @@ -81,7 +81,7 @@ public interface NDAlgebra> { * @return a feature object or `null` if it isn't present. */ @UnstableKMathAPI -public inline fun NDAlgebra.getFeature(structure: NDStructure): F? = +public inline fun AlgebraND.getFeature(structure: StructureND): F? = getFeature(structure, F::class) /** @@ -90,11 +90,11 @@ public inline fun NDAlgebra.getFeature(structur * @param structures the structures to check. * @return the array of valid structures. */ -internal fun > NDAlgebra.checkShape(vararg structures: NDStructure): Array> = +internal fun > AlgebraND.checkShape(vararg structures: StructureND): Array> = structures - .map(NDStructure::shape) + .map(StructureND::shape) .singleOrNull { !shape.contentEquals(it) } - ?.let>> { throw ShapeMismatchException(shape, it) } + ?.let>> { throw ShapeMismatchException(shape, it) } ?: structures /** @@ -103,19 +103,19 @@ internal fun > NDAlgebra.checkShape(vararg structures: N * @param element the structure to check. * @return the valid structure. */ -internal fun > NDAlgebra.checkShape(element: NDStructure): NDStructure { +internal fun > AlgebraND.checkShape(element: StructureND): StructureND { if (!element.shape.contentEquals(shape)) throw ShapeMismatchException(shape, element.shape) return element } /** - * Space of [NDStructure]. + * Space of [StructureND]. * * @param T the type of the element contained in ND structure. * @param N the type of ND structure. * @param S the type of space of structure elements. */ -public interface NDGroup> : Group>, NDAlgebra { +public interface GroupND> : Group>, AlgebraND { /** * Element-wise addition. * @@ -123,7 +123,7 @@ public interface NDGroup> : Group>, NDAlgebra, b: NDStructure): NDStructure = + public override fun add(a: StructureND, b: StructureND): StructureND = combine(a, b) { aValue, bValue -> add(aValue, bValue) } // /** @@ -144,7 +144,7 @@ public interface NDGroup> : Group>, NDAlgebra.plus(arg: T): NDStructure = this.map { value -> add(arg, value) } + public operator fun StructureND.plus(arg: T): StructureND = this.map { value -> add(arg, value) } /** * Subtracts an element from ND structure of it. @@ -153,7 +153,7 @@ public interface NDGroup> : Group>, NDAlgebra.minus(arg: T): NDStructure = this.map { value -> add(arg, -value) } + public operator fun StructureND.minus(arg: T): StructureND = this.map { value -> add(arg, -value) } /** * Adds an element to ND structure of it. @@ -162,7 +162,7 @@ public interface NDGroup> : Group>, NDAlgebra): NDStructure = arg.map { value -> add(this@plus, value) } + public operator fun T.plus(arg: StructureND): StructureND = arg.map { value -> add(this@plus, value) } /** * Subtracts an ND structure from an element of it. @@ -171,19 +171,19 @@ public interface NDGroup> : Group>, NDAlgebra): NDStructure = arg.map { value -> add(-this@minus, value) } + public operator fun T.minus(arg: StructureND): StructureND = arg.map { value -> add(-this@minus, value) } public companion object } /** - * Ring of [NDStructure]. + * Ring of [StructureND]. * * @param T the type of the element contained in ND structure. * @param N the type of ND structure. * @param R the type of ring of structure elements. */ -public interface NDRing> : Ring>, NDGroup { +public interface RingND> : Ring>, GroupND { /** * Element-wise multiplication. * @@ -191,7 +191,7 @@ public interface NDRing> : Ring>, NDGroup { * @param b the multiplier. * @return the product. */ - public override fun multiply(a: NDStructure, b: NDStructure): NDStructure = + public override fun multiply(a: StructureND, b: StructureND): StructureND = combine(a, b) { aValue, bValue -> multiply(aValue, bValue) } //TODO move to extensions after KEEP-176 @@ -203,7 +203,7 @@ public interface NDRing> : Ring>, NDGroup { * @param arg the multiplier. * @return the product. */ - public operator fun NDStructure.times(arg: T): NDStructure = this.map { value -> multiply(arg, value) } + public operator fun StructureND.times(arg: T): StructureND = this.map { value -> multiply(arg, value) } /** * Multiplies an element by a ND structure of it. @@ -212,19 +212,19 @@ public interface NDRing> : Ring>, NDGroup { * @param arg the multiplier. * @return the product. */ - public operator fun T.times(arg: NDStructure): NDStructure = arg.map { value -> multiply(this@times, value) } + public operator fun T.times(arg: StructureND): StructureND = arg.map { value -> multiply(this@times, value) } public companion object } /** - * Field of [NDStructure]. + * Field of [StructureND]. * * @param T the type of the element contained in ND structure. * @param N the type of ND structure. * @param F the type field of structure elements. */ -public interface NDField> : Field>, NDRing, ScaleOperations> { +public interface FieldND> : Field>, RingND, ScaleOperations> { /** * Element-wise division. * @@ -232,7 +232,7 @@ public interface NDField> : Field>, NDRing, * @param b the divisor. * @return the quotient. */ - public override fun divide(a: NDStructure, b: NDStructure): NDStructure = + public override fun divide(a: StructureND, b: StructureND): StructureND = combine(a, b) { aValue, bValue -> divide(aValue, bValue) } //TODO move to extensions after KEEP-176 @@ -243,7 +243,7 @@ public interface NDField> : Field>, NDRing, * @param arg the divisor. * @return the quotient. */ - public operator fun NDStructure.div(arg: T): NDStructure = this.map { value -> divide(arg, value) } + public operator fun StructureND.div(arg: T): StructureND = this.map { value -> divide(arg, value) } /** * Divides an element by an ND structure of it. @@ -252,7 +252,7 @@ public interface NDField> : Field>, NDRing, * @param arg the divisor. * @return the quotient. */ - public operator fun T.div(arg: NDStructure): NDStructure = arg.map { divide(it, this@div) } + public operator fun T.div(arg: StructureND): StructureND = arg.map { divide(it, this@div) } // @ThreadLocal // public companion object { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt similarity index 60% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt index bce3a0830..cef43d06f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt @@ -6,7 +6,7 @@ import space.kscience.kmath.structures.BufferFactory import kotlin.contracts.InvocationKind import kotlin.contracts.contract -public interface BufferNDAlgebra> : NDAlgebra { +public interface BufferAlgebraND> : AlgebraND { public val strides: Strides public val bufferFactory: BufferFactory @@ -17,24 +17,24 @@ public interface BufferNDAlgebra> : NDAlgebra { } ) - public val NDStructure.buffer: Buffer + public val StructureND.buffer: Buffer get() = when { - !shape.contentEquals(this@BufferNDAlgebra.shape) -> throw ShapeMismatchException( - this@BufferNDAlgebra.shape, + !shape.contentEquals(this@BufferAlgebraND.shape) -> throw ShapeMismatchException( + this@BufferAlgebraND.shape, shape ) - this is NDBuffer && this.strides == this@BufferNDAlgebra.strides -> this.buffer + this is NDBuffer && this.strides == this@BufferAlgebraND.strides -> this.buffer else -> bufferFactory(strides.linearSize) { offset -> get(strides.index(offset)) } } - override fun NDStructure.map(transform: A.(T) -> T): NDBuffer { + override fun StructureND.map(transform: A.(T) -> T): NDBuffer { val buffer = bufferFactory(strides.linearSize) { offset -> elementContext.transform(buffer[offset]) } return NDBuffer(strides, buffer) } - override fun NDStructure.mapIndexed(transform: A.(index: IntArray, T) -> T): NDBuffer { + override fun StructureND.mapIndexed(transform: A.(index: IntArray, T) -> T): NDBuffer { val buffer = bufferFactory(strides.linearSize) { offset -> elementContext.transform( strides.index(offset), @@ -44,7 +44,7 @@ public interface BufferNDAlgebra> : NDAlgebra { return NDBuffer(strides, buffer) } - override fun combine(a: NDStructure, b: NDStructure, transform: A.(T, T) -> T): NDBuffer { + override fun combine(a: StructureND, b: StructureND, transform: A.(T, T) -> T): NDBuffer { val buffer = bufferFactory(strides.linearSize) { offset -> elementContext.transform(a.buffer[offset], b.buffer[offset]) } @@ -52,86 +52,86 @@ public interface BufferNDAlgebra> : NDAlgebra { } } -public open class BufferedNDGroup>( +public open class BufferedGroupND>( final override val shape: IntArray, final override val elementContext: A, final override val bufferFactory: BufferFactory, -) : NDGroup, BufferNDAlgebra { +) : GroupND, BufferAlgebraND { override val strides: Strides = DefaultStrides(shape) override val zero: NDBuffer by lazy { produce { zero } } - override fun NDStructure.unaryMinus(): NDStructure = produce { -get(it) } + override fun StructureND.unaryMinus(): StructureND = produce { -get(it) } } -public open class BufferedNDRing>( +public open class BufferedRingND>( shape: IntArray, elementContext: R, bufferFactory: BufferFactory, -) : BufferedNDGroup(shape, elementContext, bufferFactory), NDRing { +) : BufferedGroupND(shape, elementContext, bufferFactory), RingND { override val one: NDBuffer by lazy { produce { one } } } -public open class BufferedNDField>( +public open class BufferedFieldND>( shape: IntArray, elementContext: R, bufferFactory: BufferFactory, -) : BufferedNDRing(shape, elementContext, bufferFactory), NDField { +) : BufferedRingND(shape, elementContext, bufferFactory), FieldND { - override fun scale(a: NDStructure, value: Double): NDStructure = a.map { it * value } + override fun scale(a: StructureND, value: Double): StructureND = a.map { it * value } } // group factories -public fun > NDAlgebra.Companion.group( +public fun > AlgebraND.Companion.group( space: A, bufferFactory: BufferFactory, vararg shape: Int, -): BufferedNDGroup = BufferedNDGroup(shape, space, bufferFactory) +): BufferedGroupND = BufferedGroupND(shape, space, bufferFactory) public inline fun , R> A.ndGroup( noinline bufferFactory: BufferFactory, vararg shape: Int, - action: BufferedNDGroup.() -> R, + action: BufferedGroupND.() -> R, ): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return NDAlgebra.group(this, bufferFactory, *shape).run(action) + return AlgebraND.group(this, bufferFactory, *shape).run(action) } //ring factories -public fun > NDAlgebra.Companion.ring( +public fun > AlgebraND.Companion.ring( ring: A, bufferFactory: BufferFactory, vararg shape: Int, -): BufferedNDRing = BufferedNDRing(shape, ring, bufferFactory) +): BufferedRingND = BufferedRingND(shape, ring, bufferFactory) public inline fun , R> A.ndRing( noinline bufferFactory: BufferFactory, vararg shape: Int, - action: BufferedNDRing.() -> R, + action: BufferedRingND.() -> R, ): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return NDAlgebra.ring(this, bufferFactory, *shape).run(action) + return AlgebraND.ring(this, bufferFactory, *shape).run(action) } //field factories -public fun > NDAlgebra.Companion.field( +public fun > AlgebraND.Companion.field( field: A, bufferFactory: BufferFactory, vararg shape: Int, -): BufferedNDField = BufferedNDField(shape, field, bufferFactory) +): BufferedFieldND = BufferedFieldND(shape, field, bufferFactory) @Suppress("UNCHECKED_CAST") -public inline fun > NDAlgebra.Companion.auto( +public inline fun > AlgebraND.Companion.auto( field: A, vararg shape: Int, -): NDField = when (field) { - RealField -> RealNDField(shape) as NDField - else -> BufferedNDField(shape, field, Buffer.Companion::auto) +): FieldND = when (field) { + RealField -> RealFieldND(shape) as FieldND + else -> BufferedFieldND(shape, field, Buffer.Companion::auto) } public inline fun , R> A.ndField( noinline bufferFactory: BufferFactory, vararg shape: Int, - action: BufferedNDField.() -> R, + action: BufferedFieldND.() -> R, ): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return NDAlgebra.field(this, bufferFactory, *shape).run(action) + return AlgebraND.field(this, bufferFactory, *shape).run(action) } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealFieldND.kt similarity index 61% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealFieldND.kt index 9f1f14af1..643eb2eb0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealFieldND.kt @@ -10,12 +10,12 @@ import kotlin.contracts.InvocationKind import kotlin.contracts.contract @OptIn(UnstableKMathAPI::class) -public class RealNDField( +public class RealFieldND( shape: IntArray, -) : BufferedNDField(shape, RealField, ::RealBuffer), - NumbersAddOperations>, - ScaleOperations>, - ExtendedField> { +) : BufferedFieldND(shape, RealField, ::RealBuffer), + NumbersAddOperations>, + ScaleOperations>, + ExtendedField> { override val zero: NDBuffer by lazy { produce { zero } } override val one: NDBuffer by lazy { produce { one } } @@ -25,18 +25,18 @@ public class RealNDField( return produce { d } } - override val NDStructure.buffer: RealBuffer + override val StructureND.buffer: RealBuffer get() = when { - !shape.contentEquals(this@RealNDField.shape) -> throw ShapeMismatchException( - this@RealNDField.shape, + !shape.contentEquals(this@RealFieldND.shape) -> throw ShapeMismatchException( + this@RealFieldND.shape, shape ) - this is NDBuffer && this.strides == this@RealNDField.strides -> this.buffer as RealBuffer + this is NDBuffer && this.strides == this@RealFieldND.strides -> this.buffer as RealBuffer else -> RealBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } } @Suppress("OVERRIDE_BY_INLINE") - override inline fun NDStructure.map( + override inline fun StructureND.map( transform: RealField.(Double) -> Double, ): NDBuffer { val buffer = RealBuffer(strides.linearSize) { offset -> RealField.transform(buffer.array[offset]) } @@ -53,7 +53,7 @@ public class RealNDField( } @Suppress("OVERRIDE_BY_INLINE") - override inline fun NDStructure.mapIndexed( + override inline fun StructureND.mapIndexed( transform: RealField.(index: IntArray, Double) -> Double, ): NDBuffer = NDBuffer( strides, @@ -66,8 +66,8 @@ public class RealNDField( @Suppress("OVERRIDE_BY_INLINE") override inline fun combine( - a: NDStructure, - b: NDStructure, + a: StructureND, + b: StructureND, transform: RealField.(Double, Double) -> Double, ): NDBuffer { val buffer = RealBuffer(strides.linearSize) { offset -> @@ -76,35 +76,35 @@ public class RealNDField( return NDBuffer(strides, buffer) } - override fun scale(a: NDStructure, value: Double): NDStructure = a.map { it * value } + override fun scale(a: StructureND, value: Double): StructureND = a.map { it * value } - override fun power(arg: NDStructure, pow: Number): NDBuffer = arg.map { power(it, pow) } + override fun power(arg: StructureND, pow: Number): NDBuffer = arg.map { power(it, pow) } - override fun exp(arg: NDStructure): NDBuffer = arg.map { exp(it) } + override fun exp(arg: StructureND): NDBuffer = arg.map { exp(it) } - override fun ln(arg: NDStructure): NDBuffer = arg.map { ln(it) } + override fun ln(arg: StructureND): NDBuffer = arg.map { ln(it) } - override fun sin(arg: NDStructure): NDBuffer = arg.map { sin(it) } - override fun cos(arg: NDStructure): NDBuffer = arg.map { cos(it) } - override fun tan(arg: NDStructure): NDBuffer = arg.map { tan(it) } - override fun asin(arg: NDStructure): NDBuffer = arg.map { asin(it) } - override fun acos(arg: NDStructure): NDBuffer = arg.map { acos(it) } - override fun atan(arg: NDStructure): NDBuffer = arg.map { atan(it) } + override fun sin(arg: StructureND): NDBuffer = arg.map { sin(it) } + override fun cos(arg: StructureND): NDBuffer = arg.map { cos(it) } + override fun tan(arg: StructureND): NDBuffer = arg.map { tan(it) } + override fun asin(arg: StructureND): NDBuffer = arg.map { asin(it) } + override fun acos(arg: StructureND): NDBuffer = arg.map { acos(it) } + override fun atan(arg: StructureND): NDBuffer = arg.map { atan(it) } - override fun sinh(arg: NDStructure): NDBuffer = arg.map { sinh(it) } - override fun cosh(arg: NDStructure): NDBuffer = arg.map { cosh(it) } - override fun tanh(arg: NDStructure): NDBuffer = arg.map { tanh(it) } - override fun asinh(arg: NDStructure): NDBuffer = arg.map { asinh(it) } - override fun acosh(arg: NDStructure): NDBuffer = arg.map { acosh(it) } - override fun atanh(arg: NDStructure): NDBuffer = arg.map { atanh(it) } + override fun sinh(arg: StructureND): NDBuffer = arg.map { sinh(it) } + override fun cosh(arg: StructureND): NDBuffer = arg.map { cosh(it) } + override fun tanh(arg: StructureND): NDBuffer = arg.map { tanh(it) } + override fun asinh(arg: StructureND): NDBuffer = arg.map { asinh(it) } + override fun acosh(arg: StructureND): NDBuffer = arg.map { acosh(it) } + override fun atanh(arg: StructureND): NDBuffer = arg.map { atanh(it) } } -public fun NDAlgebra.Companion.real(vararg shape: Int): RealNDField = RealNDField(shape) +public fun AlgebraND.Companion.real(vararg shape: Int): RealFieldND = RealFieldND(shape) /** * Produce a context for n-dimensional operations inside this real field */ -public inline fun RealField.nd(vararg shape: Int, action: RealNDField.() -> R): R { +public inline fun RealField.nd(vararg shape: Int, action: RealFieldND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return RealNDField(shape).run(action) + return RealFieldND(shape).run(action) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt similarity index 80% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt index 2085840a4..4e39dd544 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt @@ -9,10 +9,10 @@ import kotlin.contracts.InvocationKind import kotlin.contracts.contract @OptIn(UnstableKMathAPI::class) -public class ShortNDRing( +public class ShortRingND( shape: IntArray, -) : BufferedNDRing(shape, ShortRing, Buffer.Companion::auto), - NumbersAddOperations> { +) : BufferedRingND(shape, ShortRing, Buffer.Companion::auto), + NumbersAddOperations> { override val zero: NDBuffer by lazy { produce { zero } } override val one: NDBuffer by lazy { produce { one } } @@ -26,11 +26,11 @@ public class ShortNDRing( /** * Fast element production using function inlining. */ -public inline fun BufferedNDRing.produceInline(crossinline initializer: ShortRing.(Int) -> Short): NDBuffer { +public inline fun BufferedRingND.produceInline(crossinline initializer: ShortRing.(Int) -> Short): NDBuffer { return NDBuffer(strides, ShortBuffer(ShortArray(strides.linearSize) { offset -> ShortRing.initializer(offset) })) } -public inline fun ShortRing.nd(vararg shape: Int, action: ShortNDRing.() -> R): R { +public inline fun ShortRing.nd(vararg shape: Int, action: ShortRingND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return ShortNDRing(shape).run(action) + return ShortRingND(shape).run(action) } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index ac8714803..eba51a980 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -6,7 +6,7 @@ import space.kscience.kmath.structures.asSequence /** * A structure that is guaranteed to be one-dimensional */ -public interface Structure1D : NDStructure, Buffer { +public interface Structure1D : StructureND, Buffer { public override val dimension: Int get() = 1 public override operator fun get(index: IntArray): T { @@ -20,7 +20,7 @@ public interface Structure1D : NDStructure, Buffer { /** * A 1D wrapper for nd-structure */ -private inline class Structure1DWrapper(val structure: NDStructure) : Structure1D { +private inline class Structure1DWrapper(val structure: StructureND) : Structure1D { override val shape: IntArray get() = structure.shape override val size: Int get() = structure.shape[0] @@ -43,9 +43,9 @@ private inline class Buffer1DWrapper(val buffer: Buffer) : Structure1D } /** - * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch + * Represent a [StructureND] as [Structure1D]. Throw error in case of dimension mismatch */ -public fun NDStructure.as1D(): Structure1D = this as? Structure1D ?: if (shape.size == 1) { +public fun StructureND.as1D(): Structure1D = this as? Structure1D ?: if (shape.size == 1) { when (this) { is NDBuffer -> Buffer1DWrapper(this.buffer) else -> Structure1DWrapper(this) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 60dedc933..1c3b0fec8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -10,7 +10,7 @@ import kotlin.reflect.KClass * * @param T the type of items. */ -public interface Structure2D : NDStructure { +public interface Structure2D : StructureND { /** * The number of rows in this structure. */ @@ -60,7 +60,7 @@ public interface Structure2D : NDStructure { /** * A 2D wrapper for nd-structure */ -private class Structure2DWrapper(val structure: NDStructure) : Structure2D { +private class Structure2DWrapper(val structure: StructureND) : Structure2D { override val shape: IntArray get() = structure.shape override val rowNum: Int get() = shape[0] @@ -79,16 +79,16 @@ private class Structure2DWrapper(val structure: NDStructure) : Structure2D } /** - * Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch + * Represent a [StructureND] as [Structure1D]. Throw error in case of dimension mismatch */ -public fun NDStructure.as2D(): Structure2D = this as? Structure2D ?: when (shape.size) { +public fun StructureND.as2D(): Structure2D = this as? Structure2D ?: when (shape.size) { 2 -> Structure2DWrapper(this) else -> error("Can't create 2d-structure from ${shape.size}d-structure") } /** - * Expose inner [NDStructure] if possible + * Expose inner [StructureND] if possible */ -internal fun Structure2D.unwrap(): NDStructure = +internal fun Structure2D.unwrap(): StructureND = if (this is Structure2DWrapper) structure else this \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt similarity index 92% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index d758f195d..54253ba9e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -16,7 +16,7 @@ import kotlin.reflect.KClass * * @param T the type of items. */ -public interface NDStructure { +public interface StructureND { /** * The shape of structure, i.e. non-empty sequence of non-negative integers that specify sizes of dimensions of * this structure. @@ -56,9 +56,9 @@ public interface NDStructure { public companion object { /** - * Indicates whether some [NDStructure] is equal to another one. + * Indicates whether some [StructureND] is equal to another one. */ - public fun contentEquals(st1: NDStructure<*>, st2: NDStructure<*>): Boolean { + public fun contentEquals(st1: StructureND<*>, st2: StructureND<*>): Boolean { if (st1 === st2) return true // fast comparison of buffers if possible @@ -126,15 +126,15 @@ public interface NDStructure { * @param index the indices. * @return the value. */ -public operator fun NDStructure.get(vararg index: Int): T = get(index) +public operator fun StructureND.get(vararg index: Int): T = get(index) @UnstableKMathAPI -public inline fun NDStructure<*>.getFeature(): T? = getFeature(T::class) +public inline fun StructureND<*>.getFeature(): T? = getFeature(T::class) /** - * Represents mutable [NDStructure]. + * Represents mutable [StructureND]. */ -public interface MutableNDStructure : NDStructure { +public interface MutableNDStructure : StructureND { /** * Inserts an item at the specified indices. * @@ -252,7 +252,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) : } /** - * Represents [NDStructure] over [Buffer]. + * Represents [StructureND] over [Buffer]. * * @param T the type of items. * @param strides The strides to access elements of [Buffer] by linear indices. @@ -261,7 +261,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) : public open class NDBuffer( public val strides: Strides, buffer: Buffer, -) : NDStructure { +) : StructureND { init { if (strides.linearSize != buffer.size) { @@ -280,7 +280,7 @@ public open class NDBuffer( } override fun equals(other: Any?): Boolean { - return NDStructure.contentEquals(this, other as? NDStructure<*> ?: return false) + return StructureND.contentEquals(this, other as? StructureND<*> ?: return false) } override fun hashCode(): Int { @@ -307,7 +307,7 @@ public open class NDBuffer( /** * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [NDBuffer] */ -public inline fun NDStructure.mapToBuffer( +public inline fun StructureND.mapToBuffer( factory: BufferFactory = Buffer.Companion::auto, crossinline transform: (T) -> R, ): NDBuffer { @@ -338,10 +338,10 @@ public class MutableNDBuffer( override operator fun set(index: IntArray, value: T): Unit = buffer.set(strides.offset(index), value) } -public inline fun NDStructure.combine( - struct: NDStructure, +public inline fun StructureND.combine( + struct: StructureND, crossinline block: (T, T) -> T, -): NDStructure { +): StructureND { require(shape.contentEquals(struct.shape)) { "Shape mismatch in structure combination" } - return NDStructure.auto(shape) { block(this[it], struct[it]) } + return StructureND.auto(shape) { block(this[it], struct[it]) } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 7e6a2eb81..55bb68850 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.operations import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.BufferedNDRing -import space.kscience.kmath.nd.NDAlgebra +import space.kscience.kmath.nd.AlgebraND +import space.kscience.kmath.nd.BufferedRingND import space.kscience.kmath.operations.BigInt.Companion.BASE import space.kscience.kmath.operations.BigInt.Companion.BASE_SIZE import space.kscience.kmath.structures.Buffer @@ -464,5 +464,5 @@ public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigIn public inline fun MutableBuffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): MutableBuffer = boxing(size, initializer) -public fun NDAlgebra.Companion.bigInt(vararg shape: Int): BufferedNDRing = - BufferedNDRing(shape, BigIntField, Buffer.Companion::bigInt) +public fun AlgebraND.Companion.bigInt(vararg shape: Int): BufferedRingND = + BufferedRingND(shape, BigIntField, Buffer.Companion::bigInt) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt index c65af7a98..6666c88b4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.structures import space.kscience.kmath.nd.DefaultStrides -import space.kscience.kmath.nd.NDStructure import space.kscience.kmath.nd.Structure2D +import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.as2D /** @@ -25,7 +25,7 @@ internal class BufferAccessor2D( public fun create(mat: Structure2D): MutableBuffer = create { i, j -> mat[i, j] } //TODO optimize wrapper - public fun MutableBuffer.collect(): Structure2D = NDStructure.buffered( + public fun MutableBuffer.collect(): Structure2D = StructureND.buffered( DefaultStrides(intArrayOf(rowNum, colNum)), factory ) { (i, j) -> diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt index 097703f49..a8a2f2586 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.linear import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.NDStructure +import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.as2D import kotlin.test.Test import kotlin.test.assertEquals @@ -50,8 +50,8 @@ class MatrixTest { @Test fun test2DDot() { - val firstMatrix = NDStructure.auto(2, 3) { (i, j) -> (i + j).toDouble() }.as2D() - val secondMatrix = NDStructure.auto(3, 2) { (i, j) -> (i + j).toDouble() }.as2D() + val firstMatrix = StructureND.auto(2, 3) { (i, j) -> (i + j).toDouble() }.as2D() + val secondMatrix = StructureND.auto(3, 2) { (i, j) -> (i + j).toDouble() }.as2D() LinearSpace.real.run { // val firstMatrix = produce(2, 3) { i, j -> (i + j).toDouble() } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt index 3c84d7b4b..b282ee9f5 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.structures -import space.kscience.kmath.nd.NDAlgebra +import space.kscience.kmath.nd.AlgebraND import space.kscience.kmath.nd.get import space.kscience.kmath.nd.real import space.kscience.kmath.operations.invoke @@ -11,12 +11,12 @@ import kotlin.test.assertEquals internal class NDFieldTest { @Test fun verify() { - (NDAlgebra.real(12, 32)) { FieldVerifier(this, one + 3, one - 23, one * 12, 6.66) } + (AlgebraND.real(12, 32)) { FieldVerifier(this, one + 3, one - 23, one * 12, 6.66) } } @Test fun testStrides() { - val ndArray = NDAlgebra.real(10, 10).produce { (it[0] + it[1]).toDouble() } + val ndArray = AlgebraND.real(10, 10).produce { (it[0] + it[1]).toDouble() } assertEquals(ndArray[5, 5], 10.0) } } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt index e9e6e92fb..fb67f0308 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt @@ -11,7 +11,7 @@ import kotlin.test.assertEquals @Suppress("UNUSED_VARIABLE") class NumberNDFieldTest { - val algebra = NDAlgebra.real(3, 3) + val algebra = AlgebraND.real(3, 3) val array1 = algebra.produce { (i, j) -> (i + j).toDouble() } val array2 = algebra.produce { (i, j) -> (i - j).toDouble() } @@ -69,15 +69,15 @@ class NumberNDFieldTest { val division = array1.combine(array2, Double::div) } - object L2Norm : Norm, Double> { - override fun norm(arg: NDStructure): Double = + object L2Norm : Norm, Double> { + override fun norm(arg: StructureND): Double = kotlin.math.sqrt(arg.elements().sumByDouble { it.second.toDouble() }) } @Test fun testInternalContext() { algebra { - (NDAlgebra.real(*array1.shape)) { with(L2Norm) { 1 + norm(array1) + exp(array2) } } + (AlgebraND.real(*array1.shape)) { with(L2Norm) { 1 + norm(array1) + exp(array2) } } } } } diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index 4a9ca5244..b68dd2e8d 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -18,6 +18,6 @@ kotlin.sourceSets { } } -readme{ +readme { maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt index 5375113fe..26d078fcb 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt @@ -83,7 +83,7 @@ public class StatefulChain( private val state: S, private val seed: S.() -> R, private val forkState: ((S) -> S), - private val gen: suspend S.(R) -> R + private val gen: suspend S.(R) -> R, ) : Chain { private val mutex: Mutex = Mutex() private var value: R? = null @@ -145,7 +145,7 @@ public fun Chain.collect(mapper: suspend (Chain) -> R): Chain = public fun Chain.collectWithState( state: S, stateFork: (S) -> S, - mapper: suspend S.(Chain) -> R + mapper: suspend S.(Chain) -> R, ): Chain = object : Chain { override suspend fun next(): R = state.mapper(this@collectWithState) diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt index 6578af0e9..7a3a52657 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt @@ -27,7 +27,7 @@ public class AsyncFlow internal constructor(internal val deferredFlow: Flow Flow.async( dispatcher: CoroutineDispatcher = Dispatchers.Default, - block: suspend CoroutineScope.(T) -> R + block: suspend CoroutineScope.(T) -> R, ): AsyncFlow { val flow = map { LazyDeferred(dispatcher) { block(it) } } return AsyncFlow(flow) @@ -72,12 +72,12 @@ public suspend fun AsyncFlow.collect(concurrency: Int, collector: FlowCol public suspend inline fun AsyncFlow.collect( concurrency: Int, - crossinline action: suspend (value: T) -> Unit + crossinline action: suspend (value: T) -> Unit, ): Unit = collect(concurrency, object : FlowCollector { override suspend fun emit(value: T): Unit = action(value) }) public inline fun Flow.mapParallel( dispatcher: CoroutineDispatcher = Dispatchers.Default, - crossinline transform: suspend (T) -> R + crossinline transform: suspend (T) -> R, ): Flow = flatMapMerge { value -> flow { emit(transform(value)) } }.flowOn(dispatcher) diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt index efed41112..f81ad2f0d 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt @@ -13,7 +13,7 @@ import space.kscience.kmath.structures.VirtualBuffer public class RingBuffer( private val buffer: MutableBuffer, private var startIndex: Int = 0, - size: Int = 0 + size: Int = 0, ) : Buffer { private val mutex: Mutex = Mutex() diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyNDStructure.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt similarity index 62% rename from kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyNDStructure.kt rename to kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt index 51a79f44a..468b90561 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyNDStructure.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt @@ -3,13 +3,13 @@ package space.kscience.kmath.structures import kotlinx.coroutines.* import space.kscience.kmath.coroutines.Math import space.kscience.kmath.nd.DefaultStrides -import space.kscience.kmath.nd.NDStructure +import space.kscience.kmath.nd.StructureND -public class LazyNDStructure( +public class LazyStructureND( public val scope: CoroutineScope, public override val shape: IntArray, - public val function: suspend (IntArray) -> T -) : NDStructure { + public val function: suspend (IntArray) -> T, +) : StructureND { private val cache: MutableMap> = hashMapOf() public fun deferred(index: IntArray): Deferred = cache.getOrPut(index) { @@ -26,7 +26,7 @@ public class LazyNDStructure( } public override fun equals(other: Any?): Boolean { - return NDStructure.contentEquals(this, other as? NDStructure<*> ?: return false) + return StructureND.contentEquals(this, other as? StructureND<*> ?: return false) } public override fun hashCode(): Int { @@ -38,21 +38,21 @@ public class LazyNDStructure( } } -public fun NDStructure.deferred(index: IntArray): Deferred = - if (this is LazyNDStructure) deferred(index) else CompletableDeferred(get(index)) +public fun StructureND.deferred(index: IntArray): Deferred = + if (this is LazyStructureND) deferred(index) else CompletableDeferred(get(index)) -public suspend fun NDStructure.await(index: IntArray): T = - if (this is LazyNDStructure) await(index) else get(index) +public suspend fun StructureND.await(index: IntArray): T = + if (this is LazyStructureND) await(index) else get(index) /** * PENDING would benefit from KEEP-176 */ -public inline fun NDStructure.mapAsyncIndexed( +public inline fun StructureND.mapAsyncIndexed( scope: CoroutineScope, - crossinline function: suspend (T, index: IntArray) -> R -): LazyNDStructure = LazyNDStructure(scope, shape) { index -> function(get(index), index) } + crossinline function: suspend (T, index: IntArray) -> R, +): LazyStructureND = LazyStructureND(scope, shape) { index -> function(get(index), index) } -public inline fun NDStructure.mapAsync( +public inline fun StructureND.mapAsync( scope: CoroutineScope, - crossinline function: suspend (T) -> R -): LazyNDStructure = LazyNDStructure(scope, shape) { index -> function(get(index)) } + crossinline function: suspend (T) -> R, +): LazyStructureND = LazyStructureND(scope, shape) { index -> function(get(index)) } diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index 3355eda42..3c73f34e6 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -19,6 +19,6 @@ kotlin.sourceSets { } } -readme{ +readme { maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE } diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt index f7e14b29f..81b008b6a 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt @@ -1,6 +1,9 @@ package space.kscience.kmath.dimensions -import space.kscience.kmath.linear.* +import space.kscience.kmath.linear.LinearSpace +import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.linear.Point +import space.kscience.kmath.linear.transpose import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.Ring @@ -95,7 +98,7 @@ public inline class DMatrixContext>(public val context: * Produce a matrix with this context and given dimensions */ public inline fun produce( - noinline initializer: A.(i: Int, j: Int) -> T + noinline initializer: A.(i: Int, j: Int) -> T, ): DMatrix { val rows = Dimension.dim() val cols = Dimension.dim() @@ -147,9 +150,10 @@ public inline class DMatrixContext>(public val context: /** * A square unit matrix */ -public inline fun DMatrixContext.one(): DMatrix = produce { i, j -> - if (i == j) 1.0 else 0.0 -} +public inline fun DMatrixContext.one(): DMatrix = + produce { i, j -> + if (i == j) 1.0 else 0.0 + } public inline fun DMatrixContext.zero(): DMatrix = produce { _, _ -> diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index 07f95b13f..1ce2291c4 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -7,6 +7,6 @@ dependencies { implementation(project(":kmath-core")) } -readme{ +readme { maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE } \ No newline at end of file diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index 5f93af729..c79493411 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.ejml import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.Matrix -import space.kscience.kmath.nd.NDStructure +import space.kscience.kmath.nd.StructureND /** * Represents featured matrix over EJML [SimpleMatrix]. @@ -18,8 +18,8 @@ public class EjmlMatrix(public val origin: SimpleMatrix) : Matrix { override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is NDStructure<*>) return false - return NDStructure.contentEquals(this, other) + if (other !is StructureND<*>) return false + return StructureND.contentEquals(this, other) } override fun hashCode(): Int = origin.hashCode() diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt index 0bc5c111b..d5f093d63 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt @@ -7,6 +7,6 @@ import space.kscience.kmath.linear.Matrix /** * Optimized dot product for real matrices */ -public infix fun Matrix.dot(other: Matrix): Matrix = LinearSpace.real.run{ +public infix fun Matrix.dot(other: Matrix): Matrix = LinearSpace.real.run { this@dot dot other } \ No newline at end of file diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt index c538a2d99..5a644c8f9 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt @@ -6,7 +6,7 @@ import kotlin.test.assertEquals class GridTest { @Test - fun testStepGrid(){ + fun testStepGrid() { val grid = 0.0..1.0 step 0.2 assertEquals(6, grid.size) } diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index fc52c4981..067dbd9b3 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -15,6 +15,10 @@ readme { feature("piecewise", "src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt", "Piecewise functions.") feature("polynomials", "src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt", "Polynomial functions.") - feature("linear interpolation", "src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt", "Linear XY interpolator.") - feature("spline interpolation", "src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt", "Cubic spline XY interpolator.") + feature("linear interpolation", + "src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt", + "Linear XY interpolator.") + feature("spline interpolation", + "src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt", + "Cubic spline XY interpolator.") } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt index ae964b271..336a3ef3a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt @@ -17,6 +17,7 @@ public class IntegrandRelativeAccuracy(public val accuracy: Double) : IntegrandF public class IntegrandAbsoluteAccuracy(public val accuracy: Double) : IntegrandFeature public class IntegrandCalls(public val calls: Int) : IntegrandFeature + public val Integrand.calls: Int get() = getFeature()?.calls ?: 0 public class IntegrandMaxCalls(public val maxCalls: Int) : IntegrandFeature diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt index 7027e62c7..ebc53ad2e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt @@ -3,7 +3,7 @@ package space.kscience.kmath.integration /** * A general interface for all integrators */ -public interface Integrator { +public interface Integrator { /** * Run one integration pass and return a new [Integrand] with a new set of features */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt index dc5227f8b..fa978a9bc 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -24,21 +24,21 @@ public interface PolynomialInterpolator> : Interpolator public fun > PolynomialInterpolator.interpolatePolynomials( x: Buffer, - y: Buffer + y: Buffer, ): PiecewisePolynomial { val pointSet = BufferXYPointSet(x, y) return interpolatePolynomials(pointSet) } public fun > PolynomialInterpolator.interpolatePolynomials( - data: Map + data: Map, ): PiecewisePolynomial { val pointSet = BufferXYPointSet(data.keys.toList().asBuffer(), data.values.toList().asBuffer()) return interpolatePolynomials(pointSet) } public fun > PolynomialInterpolator.interpolatePolynomials( - data: List> + data: List>, ): PiecewisePolynomial { val pointSet = BufferXYPointSet(data.map { it.first }.asBuffer(), data.map { it.second }.asBuffer()) return interpolatePolynomials(pointSet) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt index c3bcad846..1ff7b6351 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt @@ -32,7 +32,7 @@ public class NDStructureColumn(public val structure: Structure2D, public v public class BufferXYPointSet( public override val x: Buffer, - public override val y: Buffer + public override val y: Buffer, ) : XYPointSet { public override val size: Int get() = x.size diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index e99eee38b..9d1b2d4d6 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -6,6 +6,6 @@ kotlin.sourceSets.commonMain { } } -readme{ +readme { maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE } diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt index d5f3965d9..ca0eba52f 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt @@ -11,7 +11,8 @@ import space.kscience.kmath.operations.RealField public interface Counter { public fun add(delta: T) public val value: T - public companion object{ + + public companion object { public fun real(): ObjectCounter = ObjectCounter(RealField) } } diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt index 9ee4a6e1e..ed76c7aa1 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt @@ -29,7 +29,7 @@ public interface Histogram> { public val bins: Iterable } -public fun interface HistogramBuilder { +public fun interface HistogramBuilder { /** * Increment appropriate bin diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt index 19128b2ac..f55080b09 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt @@ -3,9 +3,9 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.Domain import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.NDField -import space.kscience.kmath.nd.NDStructure +import space.kscience.kmath.nd.FieldND import space.kscience.kmath.nd.Strides +import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.SpaceElement @@ -22,7 +22,7 @@ public data class DomainBin>( @OptIn(UnstableKMathAPI::class) public class IndexedHistogram, V : Any>( override val context: IndexedHistogramSpace, - public val values: NDStructure, + public val values: StructureND, ) : Histogram>, SpaceElement, IndexedHistogramSpace> { override fun get(point: Point): Bin? { @@ -46,7 +46,7 @@ public interface IndexedHistogramSpace, V : Any> : Group>, ScaleOperations> { //public val valueSpace: Space public val strides: Strides - public val histogramValueSpace: NDField //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape), + public val histogramValueSpace: FieldND //= NDAlgebra.space(valueSpace, Buffer.Companion::boxing, *shape), /** * Resolve index of the bin including given [point] diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt index 3df0b1626..1407470c1 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt @@ -23,13 +23,13 @@ public class RealHistogramSpace( public val dimension: Int get() = lower.size private val shape = IntArray(binNums.size) { binNums[it] + 2 } - override val histogramValueSpace: RealNDField = NDAlgebra.real(*shape) + override val histogramValueSpace: RealFieldND = AlgebraND.real(*shape) override val strides: Strides get() = histogramValueSpace.strides private val binSize = RealBuffer(dimension) { (upper[it] - lower[it]) / binNums[it] } /** - * Get internal [NDStructure] bin index for given axis + * Get internal [StructureND] bin index for given axis */ private fun getIndex(axis: Int, value: Double): Int = when { value >= upper[axis] -> binNums[axis] + 1 // overflow @@ -69,7 +69,7 @@ public class RealHistogramSpace( } override fun produce(builder: HistogramBuilder.() -> Unit): IndexedHistogram { - val ndCounter = NDStructure.auto(strides) { Counter.real() } + val ndCounter = StructureND.auto(strides) { Counter.real() } val hBuilder = HistogramBuilder { point, value -> val index = getIndex(point) ndCounter[index].add(value.toDouble()) diff --git a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt index e83f42b4b..fc00c6cdf 100644 --- a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt @@ -44,7 +44,7 @@ internal class MultivariateHistogramTest { @Test fun testHistogramAlgebra() { - RealHistogramSpace.fromRanges( + RealHistogramSpace.fromRanges( (-1.0..1.0), (-1.0..1.0), (-1.0..1.0) diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt index 03bd096d9..b1b2a10c2 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt @@ -9,7 +9,8 @@ import space.kscience.kmath.structures.asSequence @UnstableKMathAPI -public val UnivariateDomain.center: Double get() = (range.endInclusive - range.start) / 2 +public val UnivariateDomain.center: Double + get() = (range.endInclusive - range.start) / 2 /** * A univariate bin based an a range diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index 51292cbfb..a7c0c7e01 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -8,6 +8,6 @@ dependencies { api(project(":kmath-ast")) } -readme{ +readme { maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE } \ No newline at end of file diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index dbd68b042..1ccd1bed8 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -3,7 +3,7 @@ plugins { id("ru.mipt.npm.gradle.native") } -readme{ +readme { description = """ An API and basic implementation for arranging objects in a continous memory block. """.trimIndent() diff --git a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt index 7c68e3abb..5ed3c3c9e 100644 --- a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt +++ b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt @@ -32,7 +32,8 @@ public fun MemoryReader.read(spec: MemorySpec, offset: Int): T = wi /** * Writes the object [value] with [spec] starting from [offset]. */ -public fun MemoryWriter.write(spec: MemorySpec, offset: Int, value: T): Unit = with(spec) { write(offset, value) } +public fun MemoryWriter.write(spec: MemorySpec, offset: Int, value: T): Unit = + with(spec) { write(offset, value) } /** * Reads array of [size] objects mapped by [spec] at certain [offset]. diff --git a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt index 5145b1ed4..fe15cce49 100644 --- a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt +++ b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt @@ -13,7 +13,7 @@ import kotlin.contracts.contract internal class ByteBufferMemory( val buffer: ByteBuffer, val startOffset: Int = 0, - override val size: Int = buffer.limit() + override val size: Int = buffer.limit(), ) : Memory { @Suppress("NOTHING_TO_INLINE") private inline fun position(o: Int): Int = startOffset + o @@ -100,7 +100,8 @@ public actual fun Memory.Companion.allocate(length: Int): Memory = * Wraps a [Memory] around existing [ByteArray]. This operation is unsafe since the array is not copied * and could be mutated independently from the resulting [Memory]. */ -public actual fun Memory.Companion.wrap(array: ByteArray): Memory = ByteBufferMemory(checkNotNull(ByteBuffer.wrap(array))) +public actual fun Memory.Companion.wrap(array: ByteArray): Memory = + ByteBufferMemory(checkNotNull(ByteBuffer.wrap(array))) /** * Wraps this [ByteBuffer] to [Memory] object. diff --git a/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt b/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt index 3afb6c7a2..1274959ad 100644 --- a/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt +++ b/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt @@ -4,7 +4,7 @@ package space.kscience.kmath.memory internal class NativeMemory( val array: ByteArray, val startOffset: Int = 0, - override val size: Int = array.size + override val size: Int = array.size, ) : Memory { @Suppress("NOTHING_TO_INLINE") private inline fun position(o: Int): Int = startOffset + o diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index d8ce1052a..bf73ec20f 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -7,7 +7,7 @@ import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* import space.kscience.kmath.structures.* -internal fun NDAlgebra<*, *>.checkShape(array: INDArray): INDArray { +internal fun AlgebraND<*, *>.checkShape(array: INDArray): INDArray { val arrayShape = array.shape().toIntArray() if (!shape.contentEquals(arrayShape)) throw ShapeMismatchException(shape, arrayShape) return array @@ -15,18 +15,18 @@ internal fun NDAlgebra<*, *>.checkShape(array: INDArray): INDArray { /** - * Represents [NDAlgebra] over [Nd4jArrayAlgebra]. + * Represents [AlgebraND] over [Nd4jArrayAlgebra]. * * @param T the type of ND-structure element. * @param C the type of the element context. */ -public interface Nd4jArrayAlgebra> : NDAlgebra { +public interface Nd4jArrayAlgebra> : AlgebraND { /** * Wraps [INDArray] to [N]. */ public fun INDArray.wrap(): Nd4jArrayStructure - public val NDStructure.ndArray: INDArray + public val StructureND.ndArray: INDArray get() = when { !shape.contentEquals(this@Nd4jArrayAlgebra.shape) -> throw ShapeMismatchException( this@Nd4jArrayAlgebra.shape, @@ -44,13 +44,13 @@ public interface Nd4jArrayAlgebra> : NDAlgebra { return struct } - public override fun NDStructure.map(transform: C.(T) -> T): Nd4jArrayStructure { + public override fun StructureND.map(transform: C.(T) -> T): Nd4jArrayStructure { val newStruct = ndArray.dup().wrap() newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) } return newStruct } - public override fun NDStructure.mapIndexed( + public override fun StructureND.mapIndexed( transform: C.(index: IntArray, T) -> T, ): Nd4jArrayStructure { val new = Nd4j.create(*this@Nd4jArrayAlgebra.shape).wrap() @@ -59,8 +59,8 @@ public interface Nd4jArrayAlgebra> : NDAlgebra { } public override fun combine( - a: NDStructure, - b: NDStructure, + a: StructureND, + b: StructureND, transform: C.(T, T) -> T, ): Nd4jArrayStructure { val new = Nd4j.create(*shape).wrap() @@ -70,42 +70,42 @@ public interface Nd4jArrayAlgebra> : NDAlgebra { } /** - * Represents [NDGroup] over [Nd4jArrayStructure]. + * Represents [GroupND] over [Nd4jArrayStructure]. * * @param T the type of the element contained in ND structure. * @param S the type of space of structure elements. */ -public interface Nd4JArrayGroup> : NDGroup, Nd4jArrayAlgebra { +public interface Nd4JArrayGroup> : GroupND, Nd4jArrayAlgebra { public override val zero: Nd4jArrayStructure get() = Nd4j.zeros(*shape).wrap() - public override fun add(a: NDStructure, b: NDStructure): Nd4jArrayStructure = + public override fun add(a: StructureND, b: StructureND): Nd4jArrayStructure = a.ndArray.add(b.ndArray).wrap() - public override operator fun NDStructure.minus(b: NDStructure): Nd4jArrayStructure = + public override operator fun StructureND.minus(b: StructureND): Nd4jArrayStructure = ndArray.sub(b.ndArray).wrap() - public override operator fun NDStructure.unaryMinus(): Nd4jArrayStructure = + public override operator fun StructureND.unaryMinus(): Nd4jArrayStructure = ndArray.neg().wrap() - public fun multiply(a: NDStructure, k: Number): Nd4jArrayStructure = + public fun multiply(a: StructureND, k: Number): Nd4jArrayStructure = a.ndArray.mul(k).wrap() } /** - * Represents [NDRing] over [Nd4jArrayStructure]. + * Represents [RingND] over [Nd4jArrayStructure]. * * @param T the type of the element contained in ND structure. * @param R the type of ring of structure elements. */ @OptIn(UnstableKMathAPI::class) -public interface Nd4jArrayRing> : NDRing, Nd4JArrayGroup { +public interface Nd4jArrayRing> : RingND, Nd4JArrayGroup { public override val one: Nd4jArrayStructure get() = Nd4j.ones(*shape).wrap() - public override fun multiply(a: NDStructure, b: NDStructure): Nd4jArrayStructure = + public override fun multiply(a: StructureND, b: StructureND): Nd4jArrayStructure = a.ndArray.mul(b.ndArray).wrap() // // public override operator fun Nd4jArrayStructure.minus(b: Number): Nd4jArrayStructure { @@ -131,19 +131,19 @@ public interface Nd4jArrayRing> : NDRing, Nd4JArrayGroup = intNd4jArrayRingCache.get().getOrPut(shape) { IntNd4jArrayRing(shape) } /** - * Creates an [NDRing] for [Long] values or pull it from cache if it was created previously. + * Creates an [RingND] for [Long] values or pull it from cache if it was created previously. */ public fun long(vararg shape: Int): Nd4jArrayRing = longNd4jArrayRingCache.get().getOrPut(shape) { LongNd4jArrayRing(shape) } /** - * Creates a most suitable implementation of [NDRing] using reified class. + * Creates a most suitable implementation of [RingND] using reified class. */ @Suppress("UNCHECKED_CAST") public inline fun auto(vararg shape: Int): Nd4jArrayRing> = when { @@ -155,18 +155,18 @@ public interface Nd4jArrayRing> : NDRing, Nd4JArrayGroup> : NDField, Nd4jArrayRing { +public interface Nd4jArrayField> : FieldND, Nd4jArrayRing { - public override fun divide(a: NDStructure, b: NDStructure): Nd4jArrayStructure = + public override fun divide(a: StructureND, b: StructureND): Nd4jArrayStructure = a.ndArray.div(b.ndArray).wrap() - public operator fun Number.div(b: NDStructure): Nd4jArrayStructure = b.ndArray.rdiv(this).wrap() + public operator fun Number.div(b: StructureND): Nd4jArrayStructure = b.ndArray.rdiv(this).wrap() public companion object { private val floatNd4jArrayFieldCache: ThreadLocal> = @@ -176,19 +176,19 @@ public interface Nd4jArrayField> : NDField, Nd4jArrayRing< ThreadLocal.withInitial { hashMapOf() } /** - * Creates an [NDField] for [Float] values or pull it from cache if it was created previously. + * Creates an [FieldND] for [Float] values or pull it from cache if it was created previously. */ public fun float(vararg shape: Int): Nd4jArrayRing = floatNd4jArrayFieldCache.get().getOrPut(shape) { FloatNd4jArrayField(shape) } /** - * Creates an [NDField] for [Double] values or pull it from cache if it was created previously. + * Creates an [FieldND] for [Double] values or pull it from cache if it was created previously. */ public fun real(vararg shape: Int): Nd4jArrayRing = realNd4jArrayFieldCache.get().getOrPut(shape) { RealNd4jArrayField(shape) } /** - * Creates a most suitable implementation of [NDRing] using reified class. + * Creates a most suitable implementation of [RingND] using reified class. */ @Suppress("UNCHECKED_CAST") public inline fun auto(vararg shape: Int): Nd4jArrayField> = when { @@ -200,44 +200,44 @@ public interface Nd4jArrayField> : NDField, Nd4jArrayRing< } /** - * Represents [NDField] over [Nd4jArrayRealStructure]. + * Represents [FieldND] over [Nd4jArrayRealStructure]. */ public class RealNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField { public override val elementContext: RealField get() = RealField public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asRealStructure() - override fun scale(a: NDStructure, value: Double): Nd4jArrayStructure { + override fun scale(a: StructureND, value: Double): Nd4jArrayStructure { return a.ndArray.mul(value).wrap() } - public override operator fun NDStructure.div(arg: Double): Nd4jArrayStructure { + public override operator fun StructureND.div(arg: Double): Nd4jArrayStructure { return ndArray.div(arg).wrap() } - public override operator fun NDStructure.plus(arg: Double): Nd4jArrayStructure { + public override operator fun StructureND.plus(arg: Double): Nd4jArrayStructure { return ndArray.add(arg).wrap() } - public override operator fun NDStructure.minus(arg: Double): Nd4jArrayStructure { + public override operator fun StructureND.minus(arg: Double): Nd4jArrayStructure { return ndArray.sub(arg).wrap() } - public override operator fun NDStructure.times(arg: Double): Nd4jArrayStructure { + public override operator fun StructureND.times(arg: Double): Nd4jArrayStructure { return ndArray.mul(arg).wrap() } - public override operator fun Double.div(arg: NDStructure): Nd4jArrayStructure { + public override operator fun Double.div(arg: StructureND): Nd4jArrayStructure { return arg.ndArray.rdiv(this).wrap() } - public override operator fun Double.minus(arg: NDStructure): Nd4jArrayStructure { + public override operator fun Double.minus(arg: StructureND): Nd4jArrayStructure { return arg.ndArray.rsub(this).wrap() } } /** - * Represents [NDField] over [Nd4jArrayStructure] of [Float]. + * Represents [FieldND] over [Nd4jArrayStructure] of [Float]. */ public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField { public override val elementContext: FloatField @@ -245,30 +245,30 @@ public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArra public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asFloatStructure() - override fun scale(a: NDStructure, value: Double): NDStructure = + override fun scale(a: StructureND, value: Double): StructureND = a.ndArray.mul(value).wrap() - public override operator fun NDStructure.div(arg: Float): Nd4jArrayStructure = + public override operator fun StructureND.div(arg: Float): Nd4jArrayStructure = ndArray.div(arg).wrap() - public override operator fun NDStructure.plus(arg: Float): Nd4jArrayStructure = + public override operator fun StructureND.plus(arg: Float): Nd4jArrayStructure = ndArray.add(arg).wrap() - public override operator fun NDStructure.minus(arg: Float): Nd4jArrayStructure = + public override operator fun StructureND.minus(arg: Float): Nd4jArrayStructure = ndArray.sub(arg).wrap() - public override operator fun NDStructure.times(arg: Float): Nd4jArrayStructure = + public override operator fun StructureND.times(arg: Float): Nd4jArrayStructure = ndArray.mul(arg).wrap() - public override operator fun Float.div(arg: NDStructure): Nd4jArrayStructure = + public override operator fun Float.div(arg: StructureND): Nd4jArrayStructure = arg.ndArray.rdiv(this).wrap() - public override operator fun Float.minus(arg: NDStructure): Nd4jArrayStructure = + public override operator fun Float.minus(arg: StructureND): Nd4jArrayStructure = arg.ndArray.rsub(this).wrap() } /** - * Represents [NDRing] over [Nd4jArrayIntStructure]. + * Represents [RingND] over [Nd4jArrayIntStructure]. */ public class IntNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRing { public override val elementContext: IntRing @@ -276,21 +276,21 @@ public class IntNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRi public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asIntStructure() - public override operator fun NDStructure.plus(arg: Int): Nd4jArrayStructure = + public override operator fun StructureND.plus(arg: Int): Nd4jArrayStructure = ndArray.add(arg).wrap() - public override operator fun NDStructure.minus(arg: Int): Nd4jArrayStructure = + public override operator fun StructureND.minus(arg: Int): Nd4jArrayStructure = ndArray.sub(arg).wrap() - public override operator fun NDStructure.times(arg: Int): Nd4jArrayStructure = + public override operator fun StructureND.times(arg: Int): Nd4jArrayStructure = ndArray.mul(arg).wrap() - public override operator fun Int.minus(arg: NDStructure): Nd4jArrayStructure = + public override operator fun Int.minus(arg: StructureND): Nd4jArrayStructure = arg.ndArray.rsub(this).wrap() } /** - * Represents [NDRing] over [Nd4jArrayStructure] of [Long]. + * Represents [RingND] over [Nd4jArrayStructure] of [Long]. */ public class LongNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRing { public override val elementContext: LongRing @@ -298,15 +298,15 @@ public class LongNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayR public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asLongStructure() - public override operator fun NDStructure.plus(arg: Long): Nd4jArrayStructure = + public override operator fun StructureND.plus(arg: Long): Nd4jArrayStructure = ndArray.add(arg).wrap() - public override operator fun NDStructure.minus(arg: Long): Nd4jArrayStructure = + public override operator fun StructureND.minus(arg: Long): Nd4jArrayStructure = ndArray.sub(arg).wrap() - public override operator fun NDStructure.times(arg: Long): Nd4jArrayStructure = + public override operator fun StructureND.times(arg: Long): Nd4jArrayStructure = ndArray.mul(arg).wrap() - public override operator fun Long.minus(arg: NDStructure): Nd4jArrayStructure = + public override operator fun Long.minus(arg: StructureND): Nd4jArrayStructure = arg.ndArray.rsub(this).wrap() } diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt index 415c908a8..9b4cc1a24 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt @@ -2,10 +2,10 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray import space.kscience.kmath.nd.MutableNDStructure -import space.kscience.kmath.nd.NDStructure +import space.kscience.kmath.nd.StructureND /** - * Represents a [NDStructure] wrapping an [INDArray] object. + * Represents a [StructureND] wrapping an [INDArray] object. * * @param T the type of items. */ diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt index 9a067aa29..6a8d8796c 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt @@ -8,7 +8,7 @@ import kotlin.test.fail internal class Nd4jArrayAlgebraTest { @Test fun testProduce() { - val res = with(RealNd4jArrayField(intArrayOf(2, 2))){ produce { it.sum().toDouble() } } + val res = with(RealNd4jArrayField(intArrayOf(2, 2))) { produce { it.sum().toDouble() } } val expected = (Nd4j.create(2, 2) ?: fail()).asRealStructure() expected[intArrayOf(0, 0)] = 0.0 expected[intArrayOf(0, 1)] = 1.0 diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt index 03369127d..5cf6dd26f 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt @@ -41,9 +41,9 @@ internal class Nd4jArrayStructureTest { @Test fun testHashCode() { - val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))?:fail() + val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail() val struct1 = nd1.asRealStructure() - val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))?:fail() + val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail() val struct2 = nd2.asRealStructure() assertEquals(struct1.hashCode(), struct2.hashCode()) } @@ -57,7 +57,7 @@ internal class Nd4jArrayStructureTest { @Test fun testGet() { - val nd = Nd4j.rand(10, 2, 3, 6)?:fail() + val nd = Nd4j.rand(10, 2, 3, 6) ?: fail() val struct = nd.asIntStructure() assertEquals(nd.getInt(0, 0, 0, 0), struct[0, 0, 0, 0]) } diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index 67a96937c..5b29a9e64 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -25,6 +25,6 @@ kotlin.sourceSets { } } -readme{ +readme { maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt index b5b6db1d8..dacf7a9cd 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt @@ -53,7 +53,7 @@ public fun > UnivariateDistribution.integral(from: T, to: T public fun Sampler.sampleBuffer( generator: RandomGenerator, size: Int, - bufferFactory: BufferFactory = Buffer.Companion::boxing + bufferFactory: BufferFactory = Buffer.Companion::boxing, ): Chain> { require(size > 1) //creating temporary storage once diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt index 71f3096de..ffa24fa98 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt @@ -68,7 +68,7 @@ public fun > Expression.optimizeWith( configuration: F.() -> Unit, ): OptimizationResult { require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = factory(symbols.toList(),configuration) + val problem = factory(symbols.toList(), configuration) problem.expression(this) return problem.optimize() } @@ -76,7 +76,7 @@ public fun > Expression.optimizeWith( /** * Optimize differentiable expression using specific [OptimizationProblemFactory] */ -public fun > DifferentiableExpression>.optimizeWith( +public fun > DifferentiableExpression>.optimizeWith( factory: OptimizationProblemFactory, vararg symbols: Symbol, configuration: F.() -> Unit, diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt index 881eabdac..6e1f36c8a 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt @@ -7,7 +7,7 @@ import space.kscience.kmath.chains.Chain */ public class RandomChain( public val generator: RandomGenerator, - private val gen: suspend RandomGenerator.() -> R + private val gen: suspend RandomGenerator.() -> R, ) : Chain { override suspend fun next(): R = generator.gen() diff --git a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt index d33b54818..1be436a4f 100644 --- a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt +++ b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt @@ -50,7 +50,7 @@ private fun normalSampler(method: NormalSamplerMethod, provider: UniformRandomPr } public fun Distribution.Companion.normal( - method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat + method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat, ): ContinuousSamplerDistribution = object : ContinuousSamplerDistribution() { override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler { val provider = generator.asUniformRandomProvider() @@ -66,7 +66,7 @@ public fun Distribution.Companion.normal( public fun Distribution.Companion.normal( mean: Double, sigma: Double, - method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat + method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat, ): ContinuousSamplerDistribution = object : ContinuousSamplerDistribution() { private val sigma2 = sigma.pow(2) private val norm = sigma * sqrt(PI * 2) diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api index ebb97b150..d48a9f9c8 100644 --- a/kmath-viktor/api/kmath-viktor.api +++ b/kmath-viktor/api/kmath-viktor.api @@ -26,130 +26,130 @@ public final class space/kscience/kmath/viktor/ViktorBuffer : space/kscience/kma public final synthetic fun unbox-impl ()Lorg/jetbrains/bio/viktor/F64FlatArray; } -public final class space/kscience/kmath/viktor/ViktorNDField : space/kscience/kmath/nd/NDField, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { +public final class space/kscience/kmath/viktor/ViktorFieldND : space/kscience/kmath/nd/FieldND, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { public fun ([I)V public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; - public fun acos-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; + public fun acos-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun acosh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun acosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun add (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun add-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; + public synthetic fun add (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun add-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; - public fun asin-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; + public fun asin-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun asinh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun asinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; - public fun atan-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; + public fun atan-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun atanh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun atanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/NDStructure; - public synthetic fun combine (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure; - public fun combine-ZQYDhZg (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; + public fun combine-WKhNzhk (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; - public fun cos-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; + public fun cos-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun cosh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun div (DLspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun cosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun div (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun div (Lspace/kscience/kmath/nd/NDStructure;D)Lspace/kscience/kmath/nd/NDStructure; - public fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; - public synthetic fun div (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public fun div (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public synthetic fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun div (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; + public fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public fun div (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun divide (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun divide (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; - public fun exp-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; + public fun exp-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; public fun getElementContext ()Lspace/kscience/kmath/operations/RealField; - public final fun getF64Buffer (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; + public final fun getF64Buffer (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun getOne ()Ljava/lang/Object; - public fun getOne-MSOxzaI ()Lorg/jetbrains/bio/viktor/F64Array; + public fun getOne-6kW2wQc ()Lorg/jetbrains/bio/viktor/F64Array; public fun getShape ()[I public synthetic fun getZero ()Ljava/lang/Object; - public fun getZero-MSOxzaI ()Lorg/jetbrains/bio/viktor/F64Array; - public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun getZero-6kW2wQc ()Lorg/jetbrains/bio/viktor/F64Array; + public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; - public fun ln-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun map (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure; - public fun map-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDStructure; - public fun mapIndexed-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array; - public fun minus (DLspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun ln-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; + public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; + public fun map-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/bio/viktor/F64Array; + public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; + public fun mapIndexed-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array; + public fun minus (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun minus (Lspace/kscience/kmath/nd/NDStructure;D)Lspace/kscience/kmath/nd/NDStructure; - public fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; - public synthetic fun minus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public fun minus-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; + public synthetic fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun minus (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; + public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public fun minus-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun multiply (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun number-Q7Xurp0 (Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; - public fun plus (DLspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun number-8UOKELU (Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; + public fun plus (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; - public synthetic fun plus (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public fun plus-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;D)Lorg/jetbrains/bio/viktor/F64Array; - public fun plus-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; + public synthetic fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public fun plus-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;D)Lorg/jetbrains/bio/viktor/F64Array; + public fun plus-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public fun pow (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun power-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDStructure; - public fun produce-Q7Xurp0 (Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/bio/viktor/F64Array; + public fun power-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; + public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; + public fun produce-8UOKELU (Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDStructure; + public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; - public fun scale-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;D)Lorg/jetbrains/bio/viktor/F64Array; + public fun scale-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;D)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; - public fun sin-Q7Xurp0 (Lspace/kscience/kmath/nd/NDStructure;)Lorg/jetbrains/bio/viktor/F64Array; + public fun sin-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun sinh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun sinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun sqrt (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; - public fun tan (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun tanh (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun times (DLspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun tanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun times (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun times (Lspace/kscience/kmath/nd/NDStructure;D)Lspace/kscience/kmath/nd/NDStructure; - public synthetic fun times (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Object;)Lspace/kscience/kmath/nd/NDStructure; - public fun times (Lspace/kscience/kmath/nd/NDStructure;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; - public fun times-s8yP2C4 (Lspace/kscience/kmath/nd/NDStructure;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; + public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun times (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public fun times (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun times-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryMinus (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun unaryMinus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/nd/NDStructure;)Lspace/kscience/kmath/nd/NDStructure; + public fun unaryPlus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } -public final class space/kscience/kmath/viktor/ViktorNDStructure : space/kscience/kmath/nd/MutableNDStructure { - public static final synthetic fun box-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lspace/kscience/kmath/viktor/ViktorNDStructure; +public final class space/kscience/kmath/viktor/ViktorStructureND : space/kscience/kmath/nd/MutableNDStructure { + public static final synthetic fun box-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lspace/kscience/kmath/viktor/ViktorStructureND; public static fun constructor-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lorg/jetbrains/bio/viktor/F64Array; public fun elements ()Lkotlin/sequences/Sequence; public static fun elements-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lkotlin/sequences/Sequence; @@ -174,8 +174,8 @@ public final class space/kscience/kmath/viktor/ViktorNDStructure : space/kscienc public final synthetic fun unbox-impl ()Lorg/jetbrains/bio/viktor/F64Array; } -public final class space/kscience/kmath/viktor/ViktorNDStructureKt { - public static final fun ViktorNDField ([I)Lspace/kscience/kmath/viktor/ViktorNDField; +public final class space/kscience/kmath/viktor/ViktorStructureNDKt { + public static final fun ViktorNDField ([I)Lspace/kscience/kmath/viktor/ViktorFieldND; public static final fun asStructure (Lorg/jetbrains/bio/viktor/F64Array;)Lorg/jetbrains/bio/viktor/F64Array; } diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index b79a25ea1..94744f528 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -9,6 +9,6 @@ dependencies { api("org.jetbrains.bio:viktor:1.0.1") } -readme{ +readme { maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT } \ No newline at end of file diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt deleted file mode 100644 index d791ed675..000000000 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt +++ /dev/null @@ -1,123 +0,0 @@ -package space.kscience.kmath.viktor - -import org.jetbrains.bio.viktor.F64Array -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.* -import space.kscience.kmath.operations.ExtendedField -import space.kscience.kmath.operations.NumbersAddOperations -import space.kscience.kmath.operations.RealField -import space.kscience.kmath.operations.ScaleOperations - -@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public inline class ViktorNDStructure(public val f64Buffer: F64Array) : MutableNDStructure { - public override val shape: IntArray get() = f64Buffer.shape - - public override inline fun get(index: IntArray): Double = f64Buffer.get(*index) - - public override inline fun set(index: IntArray, value: Double) { - f64Buffer.set(*index, value = value) - } - - public override fun elements(): Sequence> = - DefaultStrides(shape).indices().map { it to get(it) } -} - -public fun F64Array.asStructure(): ViktorNDStructure = ViktorNDStructure(this) - -@OptIn(UnstableKMathAPI::class) -@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public class ViktorNDField(public override val shape: IntArray) : NDField, - NumbersAddOperations>, ExtendedField>, - ScaleOperations> { - - public val NDStructure.f64Buffer: F64Array - get() = when { - !shape.contentEquals(this@ViktorNDField.shape) -> throw ShapeMismatchException( - this@ViktorNDField.shape, - shape - ) - this is ViktorNDStructure && this.f64Buffer.shape.contentEquals(this@ViktorNDField.shape) -> this.f64Buffer - else -> produce { this@f64Buffer[it] }.f64Buffer - } - - public override val zero: ViktorNDStructure by lazy { F64Array.full(init = 0.0, shape = shape).asStructure() } - - public override val one: ViktorNDStructure by lazy { F64Array.full(init = 1.0, shape = shape).asStructure() } - - private val strides: Strides = DefaultStrides(shape) - - public override val elementContext: RealField get() = RealField - - public override fun produce(initializer: RealField.(IntArray) -> Double): ViktorNDStructure = - F64Array(*shape).apply { - this@ViktorNDField.strides.indices().forEach { index -> - set(value = RealField.initializer(index), indices = index) - } - }.asStructure() - - override fun NDStructure.unaryMinus(): NDStructure = -1 * this - - public override fun NDStructure.map(transform: RealField.(Double) -> Double): ViktorNDStructure = - F64Array(*this@ViktorNDField.shape).apply { - this@ViktorNDField.strides.indices().forEach { index -> - set(value = RealField.transform(this@map[index]), indices = index) - } - }.asStructure() - - public override fun NDStructure.mapIndexed( - transform: RealField.(index: IntArray, Double) -> Double, - ): ViktorNDStructure = F64Array(*this@ViktorNDField.shape).apply { - this@ViktorNDField.strides.indices().forEach { index -> - set(value = RealField.transform(index, this@mapIndexed[index]), indices = index) - } - }.asStructure() - - public override fun combine( - a: NDStructure, - b: NDStructure, - transform: RealField.(Double, Double) -> Double, - ): ViktorNDStructure = F64Array(*shape).apply { - this@ViktorNDField.strides.indices().forEach { index -> - set(value = RealField.transform(a[index], b[index]), indices = index) - } - }.asStructure() - - public override fun add(a: NDStructure, b: NDStructure): ViktorNDStructure = - (a.f64Buffer + b.f64Buffer).asStructure() - - public override fun scale(a: NDStructure, value: Double): ViktorNDStructure = - (a.f64Buffer * value.toDouble()).asStructure() - - public override inline fun NDStructure.plus(b: NDStructure): ViktorNDStructure = - (f64Buffer + b.f64Buffer).asStructure() - - public override inline fun NDStructure.minus(b: NDStructure): ViktorNDStructure = - (f64Buffer - b.f64Buffer).asStructure() - - public override inline fun NDStructure.times(k: Number): ViktorNDStructure = - (f64Buffer * k.toDouble()).asStructure() - - public override inline fun NDStructure.plus(arg: Double): ViktorNDStructure = - (f64Buffer.plus(arg)).asStructure() - - override fun number(value: Number): ViktorNDStructure = - F64Array.full(init = value.toDouble(), shape = shape).asStructure() - - override fun sin(arg: NDStructure): ViktorNDStructure = arg.map { sin(it) } - - override fun cos(arg: NDStructure): ViktorNDStructure = arg.map { cos(it) } - - override fun asin(arg: NDStructure): ViktorNDStructure = arg.map { asin(it) } - - override fun acos(arg: NDStructure): ViktorNDStructure = arg.map { acos(it) } - - override fun atan(arg: NDStructure): ViktorNDStructure = arg.map { atan(it) } - - override fun power(arg: NDStructure, pow: Number): ViktorNDStructure = arg.map { it.pow(pow) } - - override fun exp(arg: NDStructure): ViktorNDStructure = arg.f64Buffer.exp().asStructure() - - override fun ln(arg: NDStructure): ViktorNDStructure = arg.f64Buffer.log().asStructure() -} - -public fun ViktorNDField(vararg shape: Int): ViktorNDField = ViktorNDField(shape) \ No newline at end of file diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt new file mode 100644 index 000000000..9195415c5 --- /dev/null +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt @@ -0,0 +1,123 @@ +package space.kscience.kmath.viktor + +import org.jetbrains.bio.viktor.F64Array +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.* +import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.operations.NumbersAddOperations +import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.ScaleOperations + +@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +public inline class ViktorStructureND(public val f64Buffer: F64Array) : MutableNDStructure { + public override val shape: IntArray get() = f64Buffer.shape + + public override inline fun get(index: IntArray): Double = f64Buffer.get(*index) + + public override inline fun set(index: IntArray, value: Double) { + f64Buffer.set(*index, value = value) + } + + public override fun elements(): Sequence> = + DefaultStrides(shape).indices().map { it to get(it) } +} + +public fun F64Array.asStructure(): ViktorStructureND = ViktorStructureND(this) + +@OptIn(UnstableKMathAPI::class) +@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +public class ViktorFieldND(public override val shape: IntArray) : FieldND, + NumbersAddOperations>, ExtendedField>, + ScaleOperations> { + + public val StructureND.f64Buffer: F64Array + get() = when { + !shape.contentEquals(this@ViktorFieldND.shape) -> throw ShapeMismatchException( + this@ViktorFieldND.shape, + shape + ) + this is ViktorStructureND && this.f64Buffer.shape.contentEquals(this@ViktorFieldND.shape) -> this.f64Buffer + else -> produce { this@f64Buffer[it] }.f64Buffer + } + + public override val zero: ViktorStructureND by lazy { F64Array.full(init = 0.0, shape = shape).asStructure() } + + public override val one: ViktorStructureND by lazy { F64Array.full(init = 1.0, shape = shape).asStructure() } + + private val strides: Strides = DefaultStrides(shape) + + public override val elementContext: RealField get() = RealField + + public override fun produce(initializer: RealField.(IntArray) -> Double): ViktorStructureND = + F64Array(*shape).apply { + this@ViktorFieldND.strides.indices().forEach { index -> + set(value = RealField.initializer(index), indices = index) + } + }.asStructure() + + override fun StructureND.unaryMinus(): StructureND = -1 * this + + public override fun StructureND.map(transform: RealField.(Double) -> Double): ViktorStructureND = + F64Array(*this@ViktorFieldND.shape).apply { + this@ViktorFieldND.strides.indices().forEach { index -> + set(value = RealField.transform(this@map[index]), indices = index) + } + }.asStructure() + + public override fun StructureND.mapIndexed( + transform: RealField.(index: IntArray, Double) -> Double, + ): ViktorStructureND = F64Array(*this@ViktorFieldND.shape).apply { + this@ViktorFieldND.strides.indices().forEach { index -> + set(value = RealField.transform(index, this@mapIndexed[index]), indices = index) + } + }.asStructure() + + public override fun combine( + a: StructureND, + b: StructureND, + transform: RealField.(Double, Double) -> Double, + ): ViktorStructureND = F64Array(*shape).apply { + this@ViktorFieldND.strides.indices().forEach { index -> + set(value = RealField.transform(a[index], b[index]), indices = index) + } + }.asStructure() + + public override fun add(a: StructureND, b: StructureND): ViktorStructureND = + (a.f64Buffer + b.f64Buffer).asStructure() + + public override fun scale(a: StructureND, value: Double): ViktorStructureND = + (a.f64Buffer * value.toDouble()).asStructure() + + public override inline fun StructureND.plus(b: StructureND): ViktorStructureND = + (f64Buffer + b.f64Buffer).asStructure() + + public override inline fun StructureND.minus(b: StructureND): ViktorStructureND = + (f64Buffer - b.f64Buffer).asStructure() + + public override inline fun StructureND.times(k: Number): ViktorStructureND = + (f64Buffer * k.toDouble()).asStructure() + + public override inline fun StructureND.plus(arg: Double): ViktorStructureND = + (f64Buffer.plus(arg)).asStructure() + + override fun number(value: Number): ViktorStructureND = + F64Array.full(init = value.toDouble(), shape = shape).asStructure() + + override fun sin(arg: StructureND): ViktorStructureND = arg.map { sin(it) } + + override fun cos(arg: StructureND): ViktorStructureND = arg.map { cos(it) } + + override fun asin(arg: StructureND): ViktorStructureND = arg.map { asin(it) } + + override fun acos(arg: StructureND): ViktorStructureND = arg.map { acos(it) } + + override fun atan(arg: StructureND): ViktorStructureND = arg.map { atan(it) } + + override fun power(arg: StructureND, pow: Number): ViktorStructureND = arg.map { it.pow(pow) } + + override fun exp(arg: StructureND): ViktorStructureND = arg.f64Buffer.exp().asStructure() + + override fun ln(arg: StructureND): ViktorStructureND = arg.f64Buffer.log().asStructure() +} + +public fun ViktorNDField(vararg shape: Int): ViktorFieldND = ViktorFieldND(shape) \ No newline at end of file From 206e4cbcf642a59792df62f71eb2d551df8b90ee Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 16 Mar 2021 21:17:26 +0300 Subject: [PATCH 104/393] Real -> Double --- CHANGELOG.md | 1 + docs/algebra.md | 2 +- docs/nd-structure.md | 4 +- .../kmath/benchmarks/BufferBenchmark.kt | 6 +- .../kscience/kmath/benchmarks/DotBenchmark.kt | 4 +- .../ExpressionsInterpretersBenchmark.kt | 4 +- .../kmath/benchmarks/NDFieldBenchmark.kt | 6 +- .../kmath/benchmarks/ViktorBenchmark.kt | 4 +- .../kmath/benchmarks/ViktorLogBenchmark.kt | 4 +- .../space/kscience/kmath/ast/expressions.kt | 4 +- .../kscience/kmath/ast/kotlingradSupport.kt | 6 +- .../kmath/commons/fit/fitWithAutoDiff.kt | 4 +- .../space/kscience/kmath/linear/gradient.kt | 10 +- .../kscience/kmath/structures/NDField.kt | 6 +- ...lRealNDField.kt => StreamDoubleFieldND.kt} | 36 +- .../structures/StructureReadBenchmark.kt | 2 +- .../structures/StructureWriteBenchmark.kt | 4 +- kmath-ast/README.md | 8 +- kmath-ast/docs/README-TEMPLATE.md | 8 +- .../TestESTreeConsistencyWithInterpreter.kt | 6 +- .../estree/TestESTreeOperationsSupport.kt | 10 +- .../kmath/estree/TestESTreeSpecialization.kt | 16 +- .../asm/TestAsmConsistencyWithInterpreter.kt | 6 +- .../kmath/asm/TestAsmOperationsSupport.kt | 10 +- .../kmath/asm/TestAsmSpecialization.kt | 16 +- .../kmath/ast/ParserPrecedenceTest.kt | 4 +- .../space/kscience/kmath/ast/ParserTest.kt | 4 +- .../kscience/kmath/commons/linear/CMMatrix.kt | 18 +- .../commons/transform/Transformations.kt | 3 +- .../commons/integration/IntegrationTest.kt | 2 +- .../kscience/kmath/complex/ComplexFieldND.kt | 10 +- kmath-core/api/kmath-core.api | 696 +++++++++--------- .../{RealDomain.kt => DoubleDomain.kt} | 2 +- .../kmath/domains/HyperSquareDomain.kt | 2 +- .../kmath/domains/UnconstrainedDomain.kt | 2 +- .../kmath/domains/UnivariateDomain.kt | 2 +- .../kmath/expressions/SimpleAutoDiff.kt | 2 +- .../kscience/kmath/linear/LinearSpace.kt | 4 +- .../kscience/kmath/linear/LupDecomposition.kt | 12 +- .../kscience/kmath/nd/BufferAlgebraND.kt | 2 +- .../nd/{RealFieldND.kt => DoubleFieldND.kt} | 46 +- .../kscience/kmath/operations/numbers.kt | 2 +- .../space/kscience/kmath/structures/Buffer.kt | 18 +- .../{RealBuffer.kt => DoubleBuffer.kt} | 22 +- .../kmath/structures/DoubleBufferField.kt | 272 +++++++ .../kmath/structures/FlaggedBuffer.kt | 4 +- .../kmath/structures/RealBufferField.kt | 272 ------- .../kmath/expressions/ExpressionFieldTest.kt | 8 +- .../kmath/expressions/SimpleAutoDiffTest.kt | 20 +- ...lLUSolverTest.kt => DoubleLUSolverTest.kt} | 2 +- .../{RealFieldTest.kt => DoubleFieldTest.kt} | 6 +- ...ingRealChain.kt => BlockingDoubleChain.kt} | 2 +- .../kscience/kmath/streaming/BufferFlow.kt | 12 +- .../kmath/structures/LazyStructureND.kt | 2 +- .../kscience/kmath/dimensions/Wrappers.kt | 8 +- .../kscience/kmath/ejml/EjmlLinearSpace.kt | 18 +- kmath-for-real/build.gradle.kts | 8 +- .../space/kscience/kmath/real/RealMatrix.kt | 16 +- .../space/kscience/kmath/real/RealVector.kt | 65 +- .../kotlin/space/kscience/kmath/real/grids.kt | 2 +- .../space/kscience/kmath/real/realND.kt | 10 +- ...{RealMatrixTest.kt => DoubleMatrixTest.kt} | 2 +- ...{RealVectorTest.kt => DoubleVectorTest.kt} | 14 +- .../interpolation/LinearInterpolatorTest.kt | 6 +- .../space/kscience/kmath/histogram/Counter.kt | 4 +- ...togramSpace.kt => DoubleHistogramSpace.kt} | 12 +- .../kscience/kmath/histogram/Histogram.kt | 6 +- .../histogram/MultivariateHistogramTest.kt | 15 +- .../kmath/kotlingrad/AdaptingTests.kt | 28 +- kmath-nd4j/docs/README-TEMPLATE.md | 6 +- .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 14 +- .../kscience/kmath/nd4j/Nd4jArrayIterator.kt | 4 +- .../kscience/kmath/nd4j/Nd4jArrayStructure.kt | 4 +- .../kmath/nd4j/Nd4jArrayAlgebraTest.kt | 4 +- .../kmath/nd4j/Nd4jArrayStructureTest.kt | 14 +- .../space/kscience/kmath/stat/Distribution.kt | 4 +- .../space/kscience/kmath/stat/Statistic.kt | 2 +- .../kscience/kmath/stat/distributions.kt | 6 +- kmath-viktor/api/kmath-viktor.api | 2 +- .../kmath/viktor/ViktorStructureND.kt | 22 +- 80 files changed, 968 insertions(+), 968 deletions(-) rename examples/src/main/kotlin/space/kscience/kmath/structures/{ParallelRealNDField.kt => StreamDoubleFieldND.kt} (76%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/{RealDomain.kt => DoubleDomain.kt} (95%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/{RealFieldND.kt => DoubleFieldND.kt} (67%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/{RealBuffer.kt => DoubleBuffer.kt} (53%) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBufferField.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt rename kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/{RealLUSolverTest.kt => DoubleLUSolverTest.kt} (97%) rename kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/{RealFieldTest.kt => DoubleFieldTest.kt} (59%) rename kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/{BlockingRealChain.kt => BlockingDoubleChain.kt} (82%) rename kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/{RealMatrixTest.kt => DoubleMatrixTest.kt} (99%) rename kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/{RealVectorTest.kt => DoubleVectorTest.kt} (67%) rename kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/{RealHistogramSpace.kt => DoubleHistogramSpace.kt} (92%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17486bd2b..f9e3f963e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - VectorSpace is now a vector space - Buffer factories for primitives moved to MutableBuffer.Companion - NDStructure and NDAlgebra to StructureND and AlgebraND respectively +- Real -> Double ### Deprecated diff --git a/docs/algebra.md b/docs/algebra.md index 6bfcde043..84693bb81 100644 --- a/docs/algebra.md +++ b/docs/algebra.md @@ -31,7 +31,7 @@ multiplication; - [Ring](http://mathworld.wolfram.com/Ring.html) adds multiplication and its neutral element (i.e. 1); - [Field](http://mathworld.wolfram.com/Field.html) adds division operation. -A typical implementation of `Field` is the `RealField` which works on doubles, and `VectorSpace` for `Space`. +A typical implementation of `Field` is the `DoubleField` which works on doubles, and `VectorSpace` for `Space`. In some cases algebra context can hold additional operations like `exp` or `sin`, and then it inherits appropriate interface. Also, contexts may have operations, which produce elements outside of the context. For example, `Matrix.dot` diff --git a/docs/nd-structure.md b/docs/nd-structure.md index 835304b9f..ec9b4d521 100644 --- a/docs/nd-structure.md +++ b/docs/nd-structure.md @@ -10,11 +10,11 @@ structures. In `kmath` performance depends on which particular context was used Let us consider following contexts: ```kotlin // automatically build context most suited for given type. - val autoField = NDField.auto(RealField, dim, dim) + val autoField = NDField.auto(DoubleField, dim, dim) // specialized nd-field for Double. It works as generic Double field as well val specializedField = NDField.real(dim, dim) //A generic boxing field. It should be used for objects, not primitives. - val genericField = NDField.buffered(RealField, dim, dim) + val genericField = NDField.buffered(DoubleField, dim, dim) ``` Now let us perform several tests and see which implementation is best suited for each case: diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt index 1c3bbab75..1db1d77dc 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt @@ -5,14 +5,14 @@ import kotlinx.benchmark.Scope import kotlinx.benchmark.State import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.complex +import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.MutableBuffer -import space.kscience.kmath.structures.RealBuffer @State(Scope.Benchmark) internal class BufferBenchmark { @Benchmark - fun genericRealBufferReadWrite() { - val buffer = RealBuffer(size) { it.toDouble() } + fun genericDoubleBufferReadWrite() { + val buffer = DoubleBuffer(size) { it.toDouble() } (0 until size).forEach { buffer[it] diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt index dbf373929..6a2126dc1 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt @@ -8,7 +8,7 @@ import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.ejml.EjmlLinearSpace import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.invoke -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import kotlin.random.Random @State(Scope.Benchmark) @@ -51,7 +51,7 @@ internal class DotBenchmark { @Benchmark fun bufferedDot(blackhole: Blackhole) { - LinearSpace.auto(RealField).invoke { + LinearSpace.auto(DoubleField).invoke { blackhole.consume(matrix1 dot matrix2) } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index e5cfbf9f6..0899241f9 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -10,7 +10,7 @@ import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.expressionInField import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.symbol -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol import kotlin.random.Random @@ -68,7 +68,7 @@ internal class ExpressionsInterpretersBenchmark { } private companion object { - private val algebra = RealField + private val algebra = DoubleField private val x by symbol } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt index e381a1559..09c415d9a 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -5,7 +5,7 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import space.kscience.kmath.nd.* -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.Buffer @State(Scope.Benchmark) @@ -41,8 +41,8 @@ internal class NDFieldBenchmark { private companion object { private const val dim = 1000 private const val n = 100 - private val autoField = AlgebraND.auto(RealField, dim, dim) + private val autoField = AlgebraND.auto(DoubleField, dim, dim) private val specializedField = AlgebraND.real(dim, dim) - private val genericField = AlgebraND.field(RealField, Buffer.Companion::boxing, dim, dim) + private val genericField = AlgebraND.field(DoubleField, Buffer.Companion::boxing, dim, dim) } } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt index 21c29affd..fd0188bd6 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.nd.AlgebraND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.auto import space.kscience.kmath.nd.real -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.viktor.ViktorNDField @State(Scope.Benchmark) @@ -54,7 +54,7 @@ internal class ViktorBenchmark { private const val n = 100 // automatically build context most suited for given type. - private val autoField = AlgebraND.auto(RealField, dim, dim) + private val autoField = AlgebraND.auto(DoubleField, dim, dim) private val realField = AlgebraND.real(dim, dim) private val viktorField = ViktorNDField(dim, dim) } diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt index e964f9bff..b6bd036ba 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt @@ -8,7 +8,7 @@ import org.jetbrains.bio.viktor.F64Array import space.kscience.kmath.nd.AlgebraND import space.kscience.kmath.nd.auto import space.kscience.kmath.nd.real -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.viktor.ViktorFieldND @State(Scope.Benchmark) @@ -46,7 +46,7 @@ internal class ViktorLogBenchmark { private const val n = 100 // automatically build context most suited for given type. - private val autoField = AlgebraND.auto(RealField, dim, dim) + private val autoField = AlgebraND.auto(DoubleField, dim, dim) private val realNdField = AlgebraND.real(dim, dim) private val viktorField = ViktorFieldND(intArrayOf(dim, dim)) } diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt index c342fc3ef..17c85eea5 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt @@ -1,10 +1,10 @@ package space.kscience.kmath.ast import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField fun main() { - val expr = RealField.mstInField { + val expr = DoubleField.mstInField { val x = bindSymbol("x") x * 2.0 + number(2.0) / x - 16.0 } diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt index 16304a458..23c9d5b41 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt @@ -5,7 +5,7 @@ import space.kscience.kmath.expressions.derivative import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.symbol import space.kscience.kmath.kotlingrad.differentiable -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField /** * In this example, x^2-4*x-44 function is differentiated with Kotlin∇, and the autodiff result is compared with @@ -14,11 +14,11 @@ import space.kscience.kmath.operations.RealField fun main() { val x by symbol - val actualDerivative = MstExpression(RealField, "x^2-4*x-44".parseMath()) + val actualDerivative = MstExpression(DoubleField, "x^2-4*x-44".parseMath()) .differentiable() .derivative(x) .compile() - val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() + val expectedDerivative = MstExpression(DoubleField, "2*x-4".parseMath()).compile() assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0)) } diff --git a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt index c26fb34e9..ef0c29a2d 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -8,7 +8,7 @@ import kscience.plotly.models.TraceValues import space.kscience.kmath.commons.optimization.chiSquared import space.kscience.kmath.commons.optimization.minimize import space.kscience.kmath.expressions.symbol -import space.kscience.kmath.real.RealVector +import space.kscience.kmath.real.DoubleVector import space.kscience.kmath.real.map import space.kscience.kmath.real.step import space.kscience.kmath.stat.* @@ -26,7 +26,7 @@ private val c by symbol /** * Shortcut to use buffers in plotly */ -operator fun TraceValues.invoke(vector: RealVector) { +operator fun TraceValues.invoke(vector: DoubleVector) { numbers = vector.asIterable() } diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt index 8dd3d7f6b..8940aeac9 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt @@ -1,11 +1,11 @@ package space.kscience.kmath.linear import space.kscience.kmath.real.* -import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.structures.DoubleBuffer fun main() { - val x0 = Point(0.0, 0.0, 0.0) - val sigma = Point(1.0, 1.0, 1.0) + val x0 = DoubleVector(0.0, 0.0, 0.0) + val sigma = DoubleVector(1.0, 1.0, 1.0) val gaussian: (Point) -> Double = { x -> require(x.size == x0.size) @@ -14,9 +14,9 @@ fun main() { fun ((Point) -> Double).grad(x: Point): Point { require(x.size == x0.size) - return RealBuffer(x.size) { i -> + return DoubleBuffer(x.size) { i -> val h = sigma[i] / 5 - val dVector = RealBuffer(x.size) { if (it == i) h else 0.0 } + val dVector = DoubleBuffer(x.size) { if (it == i) h else 0.0 } val f1 = invoke(x + dVector / 2) val f0 = invoke(x - dVector / 2) (f1 - f0) / h diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt index b884251c4..f7dc3280a 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.GlobalScope import org.nd4j.linalg.factory.Nd4j import space.kscience.kmath.nd.* import space.kscience.kmath.nd4j.Nd4jArrayField -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke import space.kscience.kmath.viktor.ViktorNDField import kotlin.contracts.InvocationKind @@ -24,11 +24,11 @@ fun main() { val n = 1000 // automatically build context most suited for given type. - val autoField = AlgebraND.auto(RealField, dim, dim) + val autoField = AlgebraND.auto(DoubleField, dim, dim) // specialized nd-field for Double. It works as generic Double field as well val realField = AlgebraND.real(dim, dim) //A generic boxing field. It should be used for objects, not primitives. - val boxingField = AlgebraND.field(RealField, Buffer.Companion::boxing, dim, dim) + val boxingField = AlgebraND.field(DoubleField, Buffer.Companion::boxing, dim, dim) // Nd4j specialized field. val nd4jField = Nd4jArrayField.real(dim, dim) //viktor field diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt similarity index 76% rename from examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt rename to examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt index 8b3c5dfbb..b4653b598 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -2,9 +2,9 @@ package space.kscience.kmath.structures import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.NumbersAddOperations -import space.kscience.kmath.operations.RealField import java.util.* import java.util.stream.IntStream @@ -12,14 +12,14 @@ import java.util.stream.IntStream * A demonstration implementation of NDField over Real using Java [DoubleStream] for parallel execution */ @OptIn(UnstableKMathAPI::class) -class StreamRealFieldND( +class StreamDoubleFieldND( override val shape: IntArray, -) : FieldND, +) : FieldND, NumbersAddOperations>, ExtendedField> { private val strides = DefaultStrides(shape) - override val elementContext: RealField get() = RealField + override val elementContext: DoubleField get() = DoubleField override val zero: NDBuffer by lazy { produce { zero } } override val one: NDBuffer by lazy { produce { one } } @@ -28,38 +28,38 @@ class StreamRealFieldND( return produce { d } } - private val StructureND.buffer: RealBuffer + private val StructureND.buffer: DoubleBuffer get() = when { - !shape.contentEquals(this@StreamRealFieldND.shape) -> throw ShapeMismatchException( - this@StreamRealFieldND.shape, + !shape.contentEquals(this@StreamDoubleFieldND.shape) -> throw ShapeMismatchException( + this@StreamDoubleFieldND.shape, shape ) - this is NDBuffer && this.strides == this@StreamRealFieldND.strides -> this.buffer as RealBuffer - else -> RealBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } + this is NDBuffer && this.strides == this@StreamDoubleFieldND.strides -> this.buffer as DoubleBuffer + else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } } - override fun produce(initializer: RealField.(IntArray) -> Double): NDBuffer { + override fun produce(initializer: DoubleField.(IntArray) -> Double): NDBuffer { val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset -> val index = strides.index(offset) - RealField.initializer(index) + DoubleField.initializer(index) }.toArray() return NDBuffer(strides, array.asBuffer()) } override fun StructureND.map( - transform: RealField.(Double) -> Double, + transform: DoubleField.(Double) -> Double, ): NDBuffer { - val array = Arrays.stream(buffer.array).parallel().map { RealField.transform(it) }.toArray() + val array = Arrays.stream(buffer.array).parallel().map { DoubleField.transform(it) }.toArray() return NDBuffer(strides, array.asBuffer()) } override fun StructureND.mapIndexed( - transform: RealField.(index: IntArray, Double) -> Double, + transform: DoubleField.(index: IntArray, Double) -> Double, ): NDBuffer { val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset -> - RealField.transform( + DoubleField.transform( strides.index(offset), buffer.array[offset] ) @@ -71,10 +71,10 @@ class StreamRealFieldND( override fun combine( a: StructureND, b: StructureND, - transform: RealField.(Double, Double) -> Double, + transform: DoubleField.(Double, Double) -> Double, ): NDBuffer { val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset -> - RealField.transform(a.buffer.array[offset], b.buffer.array[offset]) + DoubleField.transform(a.buffer.array[offset], b.buffer.array[offset]) }.toArray() return NDBuffer(strides, array.asBuffer()) } @@ -104,4 +104,4 @@ class StreamRealFieldND( override fun atanh(arg: StructureND): NDBuffer = arg.map { atanh(it) } } -fun AlgebraND.Companion.realWithStream(vararg shape: Int): StreamRealFieldND = StreamRealFieldND(shape) \ No newline at end of file +fun AlgebraND.Companion.realWithStream(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(shape) \ No newline at end of file diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt index 7f6d73394..89f984a5b 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt @@ -8,7 +8,7 @@ import kotlin.system.measureTimeMillis fun main() { val n = 6000 val array = DoubleArray(n * n) { 1.0 } - val buffer = RealBuffer(array) + val buffer = DoubleBuffer(array) val strides = DefaultStrides(intArrayOf(n, n)) val structure = NDBuffer(strides, buffer) diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt index 7aa5a07fd..27741be61 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt @@ -20,10 +20,10 @@ fun main() { println("Array mapping finished in $time2 millis") - val buffer = RealBuffer(DoubleArray(n * n) { 1.0 }) + val buffer = DoubleBuffer(DoubleArray(n * n) { 1.0 }) val time3 = measureTimeMillis { - val target = RealBuffer(DoubleArray(n * n)) + val target = DoubleBuffer(DoubleArray(n * n)) val res = array.forEachIndexed { index, value -> target[index] = value + 1 } diff --git a/kmath-ast/README.md b/kmath-ast/README.md index a88b6f696..1b3f70080 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -61,7 +61,7 @@ a special implementation of `Expression` with implemented `invoke` function. For example, the following builder: ```kotlin -RealField.mstInField { symbol("x") + 2 }.compile() +DoubleField.mstInField { symbol("x") + 2 }.compile() ``` … leads to generation of bytecode, which can be decompiled to the following Java class: @@ -94,8 +94,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression { This API extends MST and MstExpression, so you may optimize as both of them: ```kotlin -RealField.mstInField { symbol("x") + 2 }.compile() -RealField.expression("x+2".parseMath()) +DoubleField.mstInField { symbol("x") + 2 }.compile() +DoubleField.expression("x+2".parseMath()) ``` #### Known issues @@ -109,7 +109,7 @@ RealField.expression("x+2".parseMath()) A similar feature is also available on JS. ```kotlin -RealField.mstInField { symbol("x") + 2 }.compile() +DoubleField.mstInField { symbol("x") + 2 }.compile() ``` The code above returns expression implemented with such a JS function: diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index 2712cba75..80e48008b 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -16,7 +16,7 @@ a special implementation of `Expression` with implemented `invoke` function. For example, the following builder: ```kotlin -RealField.mstInField { symbol("x") + 2 }.compile() +DoubleField.mstInField { symbol("x") + 2 }.compile() ``` … leads to generation of bytecode, which can be decompiled to the following Java class: @@ -49,8 +49,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression { This API extends MST and MstExpression, so you may optimize as both of them: ```kotlin -RealField.mstInField { symbol("x") + 2 }.compile() -RealField.expression("x+2".parseMath()) +DoubleField.mstInField { symbol("x") + 2 }.compile() +DoubleField.expression("x+2".parseMath()) ``` #### Known issues @@ -64,7 +64,7 @@ RealField.expression("x+2".parseMath()) A similar feature is also available on JS. ```kotlin -RealField.mstInField { symbol("x") + 2 }.compile() +DoubleField.mstInField { symbol("x") + 2 }.compile() ``` The code above returns expression implemented with such a JS function: diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt index bb34254b1..683c0337c 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt @@ -5,7 +5,7 @@ import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.toComplex import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.ByteRing -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals @@ -73,7 +73,7 @@ internal class TestESTreeConsistencyWithInterpreter { @Test fun realField() { - val res1 = RealField.mstInField { + val res1 = DoubleField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), @@ -81,7 +81,7 @@ internal class TestESTreeConsistencyWithInterpreter { ) + zero }("x" to 2.0) - val res2 = RealField.mstInField { + val res2 = DoubleField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt index 590d0957d..d59c048b6 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt @@ -4,7 +4,7 @@ import space.kscience.kmath.ast.mstInExtendedField import space.kscience.kmath.ast.mstInField import space.kscience.kmath.ast.mstInGroup import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals @@ -12,28 +12,28 @@ import kotlin.test.assertEquals internal class TestESTreeOperationsSupport { @Test fun testUnaryOperationInvocation() { - val expression = RealField.mstInGroup { -bindSymbol("x") }.compile() + val expression = DoubleField.mstInGroup { -bindSymbol("x") }.compile() val res = expression("x" to 2.0) assertEquals(-2.0, res) } @Test fun testBinaryOperationInvocation() { - val expression = RealField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile() + val expression = DoubleField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile() val res = expression("x" to 2.0) assertEquals(-1.0, res) } @Test fun testConstProductInvocation() { - val res = RealField.mstInField { bindSymbol("x") * 2 }("x" to 2.0) + val res = DoubleField.mstInField { bindSymbol("x") * 2 }("x" to 2.0) assertEquals(4.0, res) } @Test fun testMultipleCalls() { val e = - RealField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } + DoubleField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } .compile() val r = Random(0) var s = 0.0 diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt index c5e43241a..6be963175 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt @@ -2,50 +2,50 @@ package space.kscience.kmath.estree import space.kscience.kmath.ast.mstInField import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals internal class TestESTreeSpecialization { @Test fun testUnaryPlus() { - val expr = RealField.mstInField { unaryOperationFunction("+")(bindSymbol("x")) }.compile() + val expr = DoubleField.mstInField { unaryOperationFunction("+")(bindSymbol("x")) }.compile() assertEquals(2.0, expr("x" to 2.0)) } @Test fun testUnaryMinus() { - val expr = RealField.mstInField { unaryOperationFunction("-")(bindSymbol("x")) }.compile() + val expr = DoubleField.mstInField { unaryOperationFunction("-")(bindSymbol("x")) }.compile() assertEquals(-2.0, expr("x" to 2.0)) } @Test fun testAdd() { - val expr = RealField.mstInField { binaryOperationFunction("+")(bindSymbol("x"), bindSymbol("x")) }.compile() + val expr = DoubleField.mstInField { binaryOperationFunction("+")(bindSymbol("x"), bindSymbol("x")) }.compile() assertEquals(4.0, expr("x" to 2.0)) } @Test fun testSine() { - val expr = RealField.mstInField { unaryOperationFunction("sin")(bindSymbol("x")) }.compile() + val expr = DoubleField.mstInField { unaryOperationFunction("sin")(bindSymbol("x")) }.compile() assertEquals(0.0, expr("x" to 0.0)) } @Test fun testMinus() { - val expr = RealField.mstInField { binaryOperationFunction("-")(bindSymbol("x"), bindSymbol("x")) }.compile() + val expr = DoubleField.mstInField { binaryOperationFunction("-")(bindSymbol("x"), bindSymbol("x")) }.compile() assertEquals(0.0, expr("x" to 2.0)) } @Test fun testDivide() { - val expr = RealField.mstInField { binaryOperationFunction("/")(bindSymbol("x"), bindSymbol("x")) }.compile() + val expr = DoubleField.mstInField { binaryOperationFunction("/")(bindSymbol("x"), bindSymbol("x")) }.compile() assertEquals(1.0, expr("x" to 2.0)) } @Test fun testPower() { - val expr = RealField + val expr = DoubleField .mstInField { binaryOperationFunction("pow")(bindSymbol("x"), number(2)) } .compile() diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt index 7cc1497d0..abc320360 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt @@ -5,7 +5,7 @@ import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.toComplex import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.ByteRing -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals @@ -73,7 +73,7 @@ internal class TestAsmConsistencyWithInterpreter { @Test fun realField() { - val res1 = RealField.mstInField { + val res1 = DoubleField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), @@ -81,7 +81,7 @@ internal class TestAsmConsistencyWithInterpreter { ) + zero }("x" to 2.0) - val res2 = RealField.mstInField { + val res2 = DoubleField.mstInField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt index 7047c824c..5d70cb76b 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt @@ -4,7 +4,7 @@ import space.kscience.kmath.ast.mstInExtendedField import space.kscience.kmath.ast.mstInField import space.kscience.kmath.ast.mstInGroup import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals @@ -12,28 +12,28 @@ import kotlin.test.assertEquals internal class TestAsmOperationsSupport { @Test fun testUnaryOperationInvocation() { - val expression = RealField.mstInGroup { -bindSymbol("x") }.compile() + val expression = DoubleField.mstInGroup { -bindSymbol("x") }.compile() val res = expression("x" to 2.0) assertEquals(-2.0, res) } @Test fun testBinaryOperationInvocation() { - val expression = RealField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile() + val expression = DoubleField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile() val res = expression("x" to 2.0) assertEquals(-1.0, res) } @Test fun testConstProductInvocation() { - val res = RealField.mstInField { bindSymbol("x") * 2 }("x" to 2.0) + val res = DoubleField.mstInField { bindSymbol("x") * 2 }("x" to 2.0) assertEquals(4.0, res) } @Test fun testMultipleCalls() { val e = - RealField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } + DoubleField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } .compile() val r = Random(0) var s = 0.0 diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt index a214ca4ad..f485260c9 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt @@ -2,50 +2,50 @@ package space.kscience.kmath.asm import space.kscience.kmath.ast.mstInField import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals internal class TestAsmSpecialization { @Test fun testUnaryPlus() { - val expr = RealField.mstInField { unaryOperationFunction("+")(bindSymbol("x")) }.compile() + val expr = DoubleField.mstInField { unaryOperationFunction("+")(bindSymbol("x")) }.compile() assertEquals(2.0, expr("x" to 2.0)) } @Test fun testUnaryMinus() { - val expr = RealField.mstInField { unaryOperationFunction("-")(bindSymbol("x")) }.compile() + val expr = DoubleField.mstInField { unaryOperationFunction("-")(bindSymbol("x")) }.compile() assertEquals(-2.0, expr("x" to 2.0)) } @Test fun testAdd() { - val expr = RealField.mstInField { binaryOperationFunction("+")(bindSymbol("x"), bindSymbol("x")) }.compile() + val expr = DoubleField.mstInField { binaryOperationFunction("+")(bindSymbol("x"), bindSymbol("x")) }.compile() assertEquals(4.0, expr("x" to 2.0)) } @Test fun testSine() { - val expr = RealField.mstInField { unaryOperationFunction("sin")(bindSymbol("x")) }.compile() + val expr = DoubleField.mstInField { unaryOperationFunction("sin")(bindSymbol("x")) }.compile() assertEquals(0.0, expr("x" to 0.0)) } @Test fun testMinus() { - val expr = RealField.mstInField { binaryOperationFunction("-")(bindSymbol("x"), bindSymbol("x")) }.compile() + val expr = DoubleField.mstInField { binaryOperationFunction("-")(bindSymbol("x"), bindSymbol("x")) }.compile() assertEquals(0.0, expr("x" to 2.0)) } @Test fun testDivide() { - val expr = RealField.mstInField { binaryOperationFunction("/")(bindSymbol("x"), bindSymbol("x")) }.compile() + val expr = DoubleField.mstInField { binaryOperationFunction("/")(bindSymbol("x"), bindSymbol("x")) }.compile() assertEquals(1.0, expr("x" to 2.0)) } @Test fun testPower() { - val expr = RealField + val expr = DoubleField .mstInField { binaryOperationFunction("pow")(bindSymbol("x"), number(2)) } .compile() diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt index 7153f4bfc..1450cab84 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt @@ -1,12 +1,12 @@ package space.kscience.kmath.ast +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.RealField import kotlin.test.Test import kotlin.test.assertEquals internal class ParserPrecedenceTest { - private val f: Field = RealField + private val f: Field = DoubleField @Test fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath())) diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt index 6807d5c5d..3d5449043 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt @@ -4,7 +4,7 @@ import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.Algebra -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals @@ -33,7 +33,7 @@ internal class ParserTest { @Test fun `evaluate MST with unary function`() { val mst = "sin(0)".parseMath() - val res = RealField.evaluate(mst) + val res = DoubleField.evaluate(mst) assertEquals(0.0, res) } diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index 4e3a44a83..4efd8383b 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -4,8 +4,8 @@ import org.apache.commons.math3.linear.* import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND -import space.kscience.kmath.operations.RealField -import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.structures.DoubleBuffer import kotlin.reflect.KClass import kotlin.reflect.cast @@ -34,15 +34,15 @@ public inline class CMVector(public val origin: RealVector) : Point { public fun RealVector.toPoint(): CMVector = CMVector(this) -public object CMLinearSpace : LinearSpace { - override val elementAlgebra: RealField get() = RealField +public object CMLinearSpace : LinearSpace { + override val elementAlgebra: DoubleField get() = DoubleField public override fun buildMatrix( rows: Int, columns: Int, - initializer: RealField.(i: Int, j: Int) -> Double, + initializer: DoubleField.(i: Int, j: Int) -> Double, ): CMMatrix { - val array = Array(rows) { i -> DoubleArray(columns) { j -> RealField.initializer(i, j) } } + val array = Array(rows) { i -> DoubleArray(columns) { j -> DoubleField.initializer(i, j) } } return CMMatrix(Array2DRowRealMatrix(array)) } @@ -64,8 +64,8 @@ public object CMLinearSpace : LinearSpace { internal fun RealMatrix.wrap(): CMMatrix = CMMatrix(this) internal fun RealVector.wrap(): CMVector = CMVector(this) - override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Point = - ArrayRealVector(DoubleArray(size) { RealField.initializer(it) }).wrap() + override fun buildVector(size: Int, initializer: DoubleField.(Int) -> Double): Point = + ArrayRealVector(DoubleArray(size) { DoubleField.initializer(it) }).wrap() override fun Matrix.plus(other: Matrix): CMMatrix = toCM().origin.add(other.toCM().origin).wrap() @@ -135,7 +135,7 @@ public object CMLinearSpace : LinearSpace { override val u: Matrix by lazy { CMMatrix(sv.u) } override val s: Matrix by lazy { CMMatrix(sv.s) } override val v: Matrix by lazy { CMMatrix(sv.v) } - override val singularValues: Point by lazy { RealBuffer(sv.singularValues) } + override val singularValues: Point by lazy { DoubleBuffer(sv.singularValues) } } else -> null }?.let(type::cast) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt index aaee594ad..ad6b6d8cd 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt @@ -6,7 +6,6 @@ import kotlinx.coroutines.flow.map import org.apache.commons.math3.transform.* import space.kscience.kmath.complex.Complex import space.kscience.kmath.streaming.chunked -import space.kscience.kmath.streaming.spread import space.kscience.kmath.structures.* @@ -17,7 +16,7 @@ public object Transformations { private fun Buffer.toArray(): Array = Array(size) { org.apache.commons.math3.complex.Complex(get(it).re, get(it).im) } - private fun Buffer.asArray() = if (this is RealBuffer) { + private fun Buffer.asArray() = if (this is DoubleBuffer) { array } else { DoubleArray(size) { i -> get(i) } diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt index 3693d5796..d163203f7 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt @@ -3,7 +3,7 @@ package space.kscience.kmath.commons.integration import org.junit.jupiter.api.Test import space.kscience.kmath.integration.integrate import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.RealField.sin +import space.kscience.kmath.operations.DoubleField.sin import kotlin.math.PI import kotlin.math.abs import kotlin.test.assertTrue diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt index 382410e45..e16962da7 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt @@ -34,15 +34,15 @@ public class ComplexFieldND( // @Suppress("OVERRIDE_BY_INLINE") // override inline fun map( // arg: AbstractNDBuffer, -// transform: RealField.(Double) -> Double, +// transform: DoubleField.(Double) -> Double, // ): RealNDElement { // check(arg) -// val array = RealBuffer(arg.strides.linearSize) { offset -> RealField.transform(arg.buffer[offset]) } +// val array = RealBuffer(arg.strides.linearSize) { offset -> DoubleField.transform(arg.buffer[offset]) } // return BufferedNDFieldElement(this, array) // } // // @Suppress("OVERRIDE_BY_INLINE") -// override inline fun produce(initializer: RealField.(IntArray) -> Double): RealNDElement { +// override inline fun produce(initializer: DoubleField.(IntArray) -> Double): RealNDElement { // val array = RealBuffer(strides.linearSize) { offset -> elementContext.initializer(strides.index(offset)) } // return BufferedNDFieldElement(this, array) // } @@ -50,7 +50,7 @@ public class ComplexFieldND( // @Suppress("OVERRIDE_BY_INLINE") // override inline fun mapIndexed( // arg: AbstractNDBuffer, -// transform: RealField.(index: IntArray, Double) -> Double, +// transform: DoubleField.(index: IntArray, Double) -> Double, // ): RealNDElement { // check(arg) // return BufferedNDFieldElement( @@ -67,7 +67,7 @@ public class ComplexFieldND( // override inline fun combine( // a: AbstractNDBuffer, // b: AbstractNDBuffer, -// transform: RealField.(Double, Double) -> Double, +// transform: DoubleField.(Double, Double) -> Double, // ): RealNDElement { // check(a, b) // val buffer = RealBuffer(strides.linearSize) { offset -> diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 2fb28d73a..8be9ff115 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -825,6 +825,78 @@ public final class space/kscience/kmath/nd/DefaultStrides$Companion { public final fun invoke ([I)Lspace/kscience/kmath/nd/Strides; } +public final class space/kscience/kmath/nd/DoubleFieldND : space/kscience/kmath/nd/BufferedFieldND, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { + public fun ([I)V + public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; + public fun acos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun acosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; + public fun asin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun asinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; + public fun atan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun atanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; + public fun cos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun cosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; + public fun exp (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; + public fun getBuffer-Udx-57Q (Lspace/kscience/kmath/nd/StructureND;)[D + public synthetic fun getOne ()Ljava/lang/Object; + public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun getZero ()Ljava/lang/Object; + public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; + public fun ln (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; + public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun pow (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun power (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; + public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; + public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; + public fun sin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun sinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; + public fun sqrt (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; + public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun tanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; +} + +public final class space/kscience/kmath/nd/DoubleFieldNDKt { + public static final fun nd (Lspace/kscience/kmath/operations/DoubleField;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun real (Lspace/kscience/kmath/nd/AlgebraND$Companion;[I)Lspace/kscience/kmath/nd/DoubleFieldND; +} + public abstract interface class space/kscience/kmath/nd/FieldND : space/kscience/kmath/nd/RingND, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/ScaleOperations { public abstract fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public abstract fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; @@ -921,78 +993,6 @@ public class space/kscience/kmath/nd/NDBuffer : space/kscience/kmath/nd/Structur public fun toString ()Ljava/lang/String; } -public final class space/kscience/kmath/nd/RealFieldND : space/kscience/kmath/nd/BufferedFieldND, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { - public fun ([I)V - public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; - public fun acos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun acosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; - public fun asin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun asinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; - public fun atan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun atanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; - public fun cos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun cosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; - public fun exp (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; - public fun getBuffer-LGjt3BI (Lspace/kscience/kmath/nd/StructureND;)[D - public synthetic fun getOne ()Ljava/lang/Object; - public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun getZero ()Ljava/lang/Object; - public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; - public fun ln (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; - public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun power (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; - public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; - public fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; - public fun sin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun sinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; - public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun tanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; -} - -public final class space/kscience/kmath/nd/RealFieldNDKt { - public static final fun nd (Lspace/kscience/kmath/operations/RealField;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun real (Lspace/kscience/kmath/nd/AlgebraND$Companion;[I)Lspace/kscience/kmath/nd/RealFieldND; -} - public abstract interface class space/kscience/kmath/nd/RingND : space/kscience/kmath/nd/GroupND, space/kscience/kmath/operations/Ring { public static final field Companion Lspace/kscience/kmath/nd/RingND$Companion; public abstract fun multiply (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; @@ -1338,6 +1338,92 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; } +public final class space/kscience/kmath/operations/DoubleField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/ScaleOperations { + public static final field INSTANCE Lspace/kscience/kmath/operations/DoubleField; + public fun acos (D)Ljava/lang/Double; + public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; + public fun acosh (D)Ljava/lang/Double; + public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun add (DD)Ljava/lang/Double; + public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun asin (D)Ljava/lang/Double; + public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; + public fun asinh (D)Ljava/lang/Double; + public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun atan (D)Ljava/lang/Double; + public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; + public fun atanh (D)Ljava/lang/Double; + public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperation (Ljava/lang/String;DD)Ljava/lang/Double; + public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Double; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun cos (D)Ljava/lang/Double; + public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; + public fun cosh (D)Ljava/lang/Double; + public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun div (DD)Ljava/lang/Double; + public fun div (DLjava/lang/Number;)Ljava/lang/Double; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun divide (DD)Ljava/lang/Double; + public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun exp (D)Ljava/lang/Double; + public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; + public fun getOne ()Ljava/lang/Double; + public synthetic fun getOne ()Ljava/lang/Object; + public fun getZero ()Ljava/lang/Double; + public synthetic fun getZero ()Ljava/lang/Object; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;D)Ljava/lang/Double; + public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public fun ln (D)Ljava/lang/Double; + public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; + public fun minus (DD)Ljava/lang/Double; + public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun multiply (DD)Ljava/lang/Double; + public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun norm (D)Ljava/lang/Double; + public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Ljava/lang/Double; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun plus (DD)Ljava/lang/Double; + public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun pow (DLjava/lang/Number;)Ljava/lang/Double; + public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun power (DLjava/lang/Number;)Ljava/lang/Double; + public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun rightSideNumberOperation (Ljava/lang/String;DLjava/lang/Number;)Ljava/lang/Double; + public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public fun scale (DD)Ljava/lang/Double; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun sin (D)Ljava/lang/Double; + public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; + public fun sinh (D)Ljava/lang/Double; + public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun sqrt (D)Ljava/lang/Double; + public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; + public fun tan (D)Ljava/lang/Double; + public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; + public fun tanh (D)Ljava/lang/Double; + public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun times (DD)Ljava/lang/Double; + public fun times (DLjava/lang/Number;)Ljava/lang/Double; + public fun times (Ljava/lang/Number;D)Ljava/lang/Double; + public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryMinus (D)Ljava/lang/Double; + public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperation (Ljava/lang/String;D)Ljava/lang/Double; + public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public fun unaryPlus (D)Ljava/lang/Double; + public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; +} + public abstract interface class space/kscience/kmath/operations/ExponentialOperations : space/kscience/kmath/operations/Algebra { public static final field ACOSH_OPERATION Ljava/lang/String; public static final field ASINH_OPERATION Ljava/lang/String; @@ -1877,92 +1963,6 @@ public final class space/kscience/kmath/operations/PowerOperations$DefaultImpls public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } -public final class space/kscience/kmath/operations/RealField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/ScaleOperations { - public static final field INSTANCE Lspace/kscience/kmath/operations/RealField; - public fun acos (D)Ljava/lang/Double; - public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; - public fun acosh (D)Ljava/lang/Double; - public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun add (DD)Ljava/lang/Double; - public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun asin (D)Ljava/lang/Double; - public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; - public fun asinh (D)Ljava/lang/Double; - public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun atan (D)Ljava/lang/Double; - public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; - public fun atanh (D)Ljava/lang/Double; - public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;DD)Ljava/lang/Double; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Double; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun cos (D)Ljava/lang/Double; - public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; - public fun cosh (D)Ljava/lang/Double; - public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun div (DD)Ljava/lang/Double; - public fun div (DLjava/lang/Number;)Ljava/lang/Double; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun divide (DD)Ljava/lang/Double; - public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun exp (D)Ljava/lang/Double; - public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; - public fun getOne ()Ljava/lang/Double; - public synthetic fun getOne ()Ljava/lang/Object; - public fun getZero ()Ljava/lang/Double; - public synthetic fun getZero ()Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;D)Ljava/lang/Double; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public fun ln (D)Ljava/lang/Double; - public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (DD)Ljava/lang/Double; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (DD)Ljava/lang/Double; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun norm (D)Ljava/lang/Double; - public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object; - public fun number (Ljava/lang/Number;)Ljava/lang/Double; - public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun plus (DD)Ljava/lang/Double; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun pow (DLjava/lang/Number;)Ljava/lang/Double; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun power (DLjava/lang/Number;)Ljava/lang/Double; - public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;DLjava/lang/Number;)Ljava/lang/Double; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public fun scale (DD)Ljava/lang/Double; - public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; - public fun sin (D)Ljava/lang/Double; - public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; - public fun sinh (D)Ljava/lang/Double; - public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (D)Ljava/lang/Double; - public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; - public fun tan (D)Ljava/lang/Double; - public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; - public fun tanh (D)Ljava/lang/Double; - public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun times (DD)Ljava/lang/Double; - public fun times (DLjava/lang/Number;)Ljava/lang/Double; - public fun times (Ljava/lang/Number;D)Ljava/lang/Double; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryMinus (D)Ljava/lang/Double; - public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;D)Ljava/lang/Double; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public fun unaryPlus (D)Ljava/lang/Double; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; -} - public abstract interface class space/kscience/kmath/operations/Ring : space/kscience/kmath/operations/Group, space/kscience/kmath/operations/RingOperations { public abstract fun getOne ()Ljava/lang/Object; } @@ -2135,6 +2135,193 @@ public final class space/kscience/kmath/structures/BufferOperationKt { public static final fun toList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List; } +public final class space/kscience/kmath/structures/DoubleBuffer : space/kscience/kmath/structures/MutableBuffer { + public static final synthetic fun box-impl ([D)Lspace/kscience/kmath/structures/DoubleBuffer; + public static fun constructor-impl ([D)[D + public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z + public static fun contentEquals-impl ([DLspace/kscience/kmath/structures/Buffer;)Z + public synthetic fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun copy-Dv3HvWU ()[D + public static fun copy-Dv3HvWU ([D)[D + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl ([DLjava/lang/Object;)Z + public static final fun equals-impl0 ([D[D)Z + public fun get (I)Ljava/lang/Double; + public synthetic fun get (I)Ljava/lang/Object; + public static fun get-impl ([DI)Ljava/lang/Double; + public final fun getArray ()[D + public fun getSize ()I + public static fun getSize-impl ([D)I + public fun hashCode ()I + public static fun hashCode-impl ([D)I + public synthetic fun iterator ()Ljava/util/Iterator; + public fun iterator ()Lkotlin/collections/DoubleIterator; + public static fun iterator-impl ([D)Lkotlin/collections/DoubleIterator; + public fun set (ID)V + public synthetic fun set (ILjava/lang/Object;)V + public static fun set-impl ([DID)V + public fun toString ()Ljava/lang/String; + public static fun toString-impl ([D)Ljava/lang/String; + public final synthetic fun unbox-impl ()[D +} + +public final class space/kscience/kmath/structures/DoubleBufferField : space/kscience/kmath/operations/ExtendedField { + public fun (I)V + public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; + public fun acos-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun acosh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun add-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; + public fun asin-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun asinh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; + public fun atan-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun atanh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; + public fun cos-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun cosh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun div (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; + public fun div (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun divide-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; + public fun exp-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun getOne ()Ljava/lang/Object; + public fun getOne ()Lspace/kscience/kmath/structures/Buffer; + public final fun getSize ()I + public synthetic fun getZero ()Ljava/lang/Object; + public fun getZero ()Lspace/kscience/kmath/structures/Buffer; + public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; + public fun ln-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun multiply-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun pow (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun power-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D + public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; + public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;D)[D + public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; + public fun sin-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun sinh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; + public fun sqrt (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; + public fun tan-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun tanh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; + public fun times (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryPlus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; +} + +public final class space/kscience/kmath/structures/DoubleBufferFieldOperations : space/kscience/kmath/operations/ExtendedFieldOperations { + public static final field INSTANCE Lspace/kscience/kmath/structures/DoubleBufferFieldOperations; + public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; + public fun acos-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun acosh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun add-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; + public fun asin-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun asinh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; + public fun atan-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun atanh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; + public fun cos-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun cosh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun div (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun divide-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; + public fun exp-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; + public fun ln-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun multiply-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun pow (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun power-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D + public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; + public fun sin-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun sinh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; + public fun sqrt (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; + public fun tan-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun tanh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryMinus-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryPlus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; +} + +public final class space/kscience/kmath/structures/DoubleBufferKt { + public static final fun DoubleBuffer (ILkotlin/jvm/functions/Function1;)[D + public static final fun DoubleBuffer ([D)[D + public static final fun asBuffer ([D)[D + public static final fun contentEquals-2c9zdjM ([D[D)Z + public static final fun toDoubleArray (Lspace/kscience/kmath/structures/Buffer;)[D +} + public abstract interface class space/kscience/kmath/structures/FlaggedBuffer : space/kscience/kmath/structures/Buffer { public abstract fun getFlag (I)B } @@ -2144,13 +2331,13 @@ public final class space/kscience/kmath/structures/FlaggedBuffer$DefaultImpls { } public final class space/kscience/kmath/structures/FlaggedBufferKt { - public static final fun forEachValid (Lspace/kscience/kmath/structures/FlaggedRealBuffer;Lkotlin/jvm/functions/Function1;)V + public static final fun forEachValid (Lspace/kscience/kmath/structures/FlaggedDoubleBuffer;Lkotlin/jvm/functions/Function1;)V public static final fun hasFlag (Lspace/kscience/kmath/structures/FlaggedBuffer;ILspace/kscience/kmath/structures/ValueFlag;)Z public static final fun isMissing (Lspace/kscience/kmath/structures/FlaggedBuffer;I)Z public static final fun isValid (Lspace/kscience/kmath/structures/FlaggedBuffer;I)Z } -public final class space/kscience/kmath/structures/FlaggedRealBuffer : space/kscience/kmath/structures/Buffer, space/kscience/kmath/structures/FlaggedBuffer { +public final class space/kscience/kmath/structures/FlaggedDoubleBuffer : space/kscience/kmath/structures/Buffer, space/kscience/kmath/structures/FlaggedBuffer { public fun ([D[B)V public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z public fun get (I)Ljava/lang/Double; @@ -2317,10 +2504,10 @@ public abstract interface class space/kscience/kmath/structures/MutableBuffer : public final class space/kscience/kmath/structures/MutableBuffer$Companion { public final fun auto (Lkotlin/reflect/KClass;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableBuffer; public final fun boxing (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableBuffer; + public final fun double-CZ9oacQ (ILkotlin/jvm/functions/Function1;)[D public final fun float-YxruXGw (ILkotlin/jvm/functions/Function1;)[F public final fun int-Ye6GY2U (ILkotlin/jvm/functions/Function1;)[I public final fun long-BuQOeTY (ILkotlin/jvm/functions/Function1;)[J - public final fun real-8hrHhI4 (ILkotlin/jvm/functions/Function1;)[D public final fun short-1yRgbGw (ILkotlin/jvm/functions/Function1;)[S } @@ -2388,193 +2575,6 @@ public final class space/kscience/kmath/structures/ReadOnlyBuffer : space/kscien public final synthetic fun unbox-impl ()Lspace/kscience/kmath/structures/MutableBuffer; } -public final class space/kscience/kmath/structures/RealBuffer : space/kscience/kmath/structures/MutableBuffer { - public static final synthetic fun box-impl ([D)Lspace/kscience/kmath/structures/RealBuffer; - public static fun constructor-impl ([D)[D - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z - public static fun contentEquals-impl ([DLspace/kscience/kmath/structures/Buffer;)Z - public synthetic fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; - public fun copy-88GwAag ()[D - public static fun copy-88GwAag ([D)[D - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl ([DLjava/lang/Object;)Z - public static final fun equals-impl0 ([D[D)Z - public fun get (I)Ljava/lang/Double; - public synthetic fun get (I)Ljava/lang/Object; - public static fun get-impl ([DI)Ljava/lang/Double; - public final fun getArray ()[D - public fun getSize ()I - public static fun getSize-impl ([D)I - public fun hashCode ()I - public static fun hashCode-impl ([D)I - public synthetic fun iterator ()Ljava/util/Iterator; - public fun iterator ()Lkotlin/collections/DoubleIterator; - public static fun iterator-impl ([D)Lkotlin/collections/DoubleIterator; - public fun set (ID)V - public synthetic fun set (ILjava/lang/Object;)V - public static fun set-impl ([DID)V - public fun toString ()Ljava/lang/String; - public static fun toString-impl ([D)Ljava/lang/String; - public final synthetic fun unbox-impl ()[D -} - -public final class space/kscience/kmath/structures/RealBufferField : space/kscience/kmath/operations/ExtendedField { - public fun (I)V - public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; - public fun acos-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun acosh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun add-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; - public fun asin-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun asinh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; - public fun atan-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun atanh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; - public fun cos-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun cosh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public fun div (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun divide-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; - public fun exp-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun getOne ()Ljava/lang/Object; - public fun getOne ()Lspace/kscience/kmath/structures/Buffer; - public final fun getSize ()I - public synthetic fun getZero ()Ljava/lang/Object; - public fun getZero ()Lspace/kscience/kmath/structures/Buffer; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; - public fun ln-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun power-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; - public fun scale-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;D)[D - public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; - public fun sin-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun sinh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; - public fun tan-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun tanh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public fun times (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; -} - -public final class space/kscience/kmath/structures/RealBufferFieldOperations : space/kscience/kmath/operations/ExtendedFieldOperations { - public static final field INSTANCE Lspace/kscience/kmath/structures/RealBufferFieldOperations; - public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; - public fun acos-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun acosh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun add-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; - public fun asin-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun asinh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; - public fun atan-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun atanh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; - public fun cos-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun cosh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun divide-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; - public fun exp-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; - public fun ln-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun power-8hrHhI4 (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D - public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; - public fun sin-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun sinh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; - public fun tan-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun tanh-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryMinus-LGjt3BI (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; -} - -public final class space/kscience/kmath/structures/RealBufferKt { - public static final fun RealBuffer (ILkotlin/jvm/functions/Function1;)[D - public static final fun RealBuffer ([D)[D - public static final fun asBuffer ([D)[D - public static final fun contentEquals-2uVC2J0 ([D[D)Z - public static final fun toDoubleArray (Lspace/kscience/kmath/structures/Buffer;)[D -} - public final class space/kscience/kmath/structures/ShortBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl ([S)Lspace/kscience/kmath/structures/ShortBuffer; public static fun constructor-impl ([S)[S diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt index c20cbfec1..057a4a344 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt @@ -23,7 +23,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI * @author Alexander Nozik */ @UnstableKMathAPI -public interface RealDomain : Domain { +public interface DoubleDomain : Domain { /** * Global lower edge diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt index c948f8672..a15d04b4c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt @@ -27,7 +27,7 @@ import space.kscience.kmath.structures.indices * @author Alexander Nozik */ @UnstableKMathAPI -public class HyperSquareDomain(private val lower: Buffer, private val upper: Buffer) : RealDomain { +public class HyperSquareDomain(private val lower: Buffer, private val upper: Buffer) : DoubleDomain { public override val dimension: Int get() = lower.size public override operator fun contains(point: Point): Boolean = point.indices.all { i -> diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt index 002caac50..79f33fe05 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt @@ -19,7 +19,7 @@ import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI @UnstableKMathAPI -public class UnconstrainedDomain(public override val dimension: Int) : RealDomain { +public class UnconstrainedDomain(public override val dimension: Int) : DoubleDomain { public override operator fun contains(point: Point): Boolean = true public override fun getLowerBound(num: Int): Double = Double.NEGATIVE_INFINITY diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt index d20349960..6f737bd38 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt @@ -4,7 +4,7 @@ import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI @UnstableKMathAPI -public inline class UnivariateDomain(public val range: ClosedFloatingPointRange) : RealDomain { +public inline class UnivariateDomain(public val range: ClosedFloatingPointRange) : DoubleDomain { public override val dimension: Int get() = 1 public operator fun contains(d: Double): Boolean = range.contains(d) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt index 4b5b3311e..4b0d402ed 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -198,7 +198,7 @@ public open class SimpleAutoDiffField>( * Example: * ``` * val x by symbol // define variable(s) and their values - * val y = RealField.withAutoDiff() { sqr(x) + 5 * x + 3 } // write formulate in deriv context + * val y = DoubleField.withAutoDiff() { sqr(x) + 5 * x + 3 } // write formulate in deriv context * assertEquals(17.0, y.x) // the value of result (y) * assertEquals(9.0, x.d) // dy/dx * ``` diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index e8c7d119b..6a587270b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -5,7 +5,7 @@ import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.structures.DoubleBuffer import kotlin.reflect.KClass /** @@ -176,7 +176,7 @@ public interface LinearSpace> { bufferFactory: BufferFactory = Buffer.Companion::boxing, ): LinearSpace = BufferedLinearSpace(algebra, bufferFactory) - public val real: LinearSpace = buffered(RealField, ::RealBuffer) + public val real: LinearSpace = buffered(DoubleField, ::DoubleBuffer) /** * Automatic buffered matrix, unboxed if it is possible diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt index eed50ec28..7a6495638 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt @@ -4,9 +4,9 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.getFeature import space.kscience.kmath.operations.* import space.kscience.kmath.structures.BufferAccessor2D +import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableBufferFactory -import space.kscience.kmath.structures.RealBuffer /** * Common implementation of [LupDecompositionFeature]. @@ -151,8 +151,8 @@ public inline fun > LinearSpace>.lup( noinline checkSingular: (T) -> Boolean, ): LupDecomposition = lup(MutableBuffer.Companion::auto, matrix, checkSingular) -public fun LinearSpace.lup(matrix: Matrix): LupDecomposition = - lup(::RealBuffer, matrix) { it < 1e-11 } +public fun LinearSpace.lup(matrix: Matrix): LupDecomposition = + lup(::DoubleBuffer, matrix) { it < 1e-11 } public fun LupDecomposition.solveWithLup( factory: MutableBufferFactory, @@ -228,9 +228,9 @@ public inline fun > LinearSpace>.inverseWi @OptIn(UnstableKMathAPI::class) -public fun LinearSpace.solveWithLup(a: Matrix, b: Matrix): Matrix { +public fun LinearSpace.solveWithLup(a: Matrix, b: Matrix): Matrix { // Use existing decomposition if it is provided by matrix - val bufferFactory: MutableBufferFactory = ::RealBuffer + val bufferFactory: MutableBufferFactory = ::DoubleBuffer val decomposition: LupDecomposition = a.getFeature() ?: lup(bufferFactory, a) { it < 1e-11 } return decomposition.solveWithLup(bufferFactory, b) } @@ -238,5 +238,5 @@ public fun LinearSpace.solveWithLup(a: Matrix, b: Mat /** * Inverses a square matrix using LUP decomposition. Non square matrix will throw a error. */ -public fun LinearSpace.inverseWithLup(matrix: Matrix): Matrix = +public fun LinearSpace.inverseWithLup(matrix: Matrix): Matrix = solveWithLup(matrix, one(matrix.rowNum, matrix.colNum)) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt index cef43d06f..b81eb9519 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt @@ -123,7 +123,7 @@ public inline fun > AlgebraND.Companion.auto( field: A, vararg shape: Int, ): FieldND = when (field) { - RealField -> RealFieldND(shape) as FieldND + DoubleField -> DoubleFieldND(shape) as FieldND else -> BufferedFieldND(shape, field, Buffer.Companion::auto) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealFieldND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt similarity index 67% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealFieldND.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt index 643eb2eb0..a7a9d8935 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealFieldND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt @@ -1,18 +1,18 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.NumbersAddOperations -import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.structures.DoubleBuffer import kotlin.contracts.InvocationKind import kotlin.contracts.contract @OptIn(UnstableKMathAPI::class) -public class RealFieldND( +public class DoubleFieldND( shape: IntArray, -) : BufferedFieldND(shape, RealField, ::RealBuffer), +) : BufferedFieldND(shape, DoubleField, ::DoubleBuffer), NumbersAddOperations>, ScaleOperations>, ExtendedField> { @@ -25,40 +25,40 @@ public class RealFieldND( return produce { d } } - override val StructureND.buffer: RealBuffer + override val StructureND.buffer: DoubleBuffer get() = when { - !shape.contentEquals(this@RealFieldND.shape) -> throw ShapeMismatchException( - this@RealFieldND.shape, + !shape.contentEquals(this@DoubleFieldND.shape) -> throw ShapeMismatchException( + this@DoubleFieldND.shape, shape ) - this is NDBuffer && this.strides == this@RealFieldND.strides -> this.buffer as RealBuffer - else -> RealBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } + this is NDBuffer && this.strides == this@DoubleFieldND.strides -> this.buffer as DoubleBuffer + else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } } @Suppress("OVERRIDE_BY_INLINE") override inline fun StructureND.map( - transform: RealField.(Double) -> Double, + transform: DoubleField.(Double) -> Double, ): NDBuffer { - val buffer = RealBuffer(strides.linearSize) { offset -> RealField.transform(buffer.array[offset]) } + val buffer = DoubleBuffer(strides.linearSize) { offset -> DoubleField.transform(buffer.array[offset]) } return NDBuffer(strides, buffer) } @Suppress("OVERRIDE_BY_INLINE") - override inline fun produce(initializer: RealField.(IntArray) -> Double): NDBuffer { + override inline fun produce(initializer: DoubleField.(IntArray) -> Double): NDBuffer { val array = DoubleArray(strides.linearSize) { offset -> val index = strides.index(offset) - RealField.initializer(index) + DoubleField.initializer(index) } - return NDBuffer(strides, RealBuffer(array)) + return NDBuffer(strides, DoubleBuffer(array)) } @Suppress("OVERRIDE_BY_INLINE") override inline fun StructureND.mapIndexed( - transform: RealField.(index: IntArray, Double) -> Double, + transform: DoubleField.(index: IntArray, Double) -> Double, ): NDBuffer = NDBuffer( strides, - buffer = RealBuffer(strides.linearSize) { offset -> - RealField.transform( + buffer = DoubleBuffer(strides.linearSize) { offset -> + DoubleField.transform( strides.index(offset), buffer.array[offset] ) @@ -68,10 +68,10 @@ public class RealFieldND( override inline fun combine( a: StructureND, b: StructureND, - transform: RealField.(Double, Double) -> Double, + transform: DoubleField.(Double, Double) -> Double, ): NDBuffer { - val buffer = RealBuffer(strides.linearSize) { offset -> - RealField.transform(a.buffer.array[offset], b.buffer.array[offset]) + val buffer = DoubleBuffer(strides.linearSize) { offset -> + DoubleField.transform(a.buffer.array[offset], b.buffer.array[offset]) } return NDBuffer(strides, buffer) } @@ -99,12 +99,12 @@ public class RealFieldND( override fun atanh(arg: StructureND): NDBuffer = arg.map { atanh(it) } } -public fun AlgebraND.Companion.real(vararg shape: Int): RealFieldND = RealFieldND(shape) +public fun AlgebraND.Companion.real(vararg shape: Int): DoubleFieldND = DoubleFieldND(shape) /** * Produce a context for n-dimensional operations inside this real field */ -public inline fun RealField.nd(vararg shape: Int, action: RealFieldND.() -> R): R { +public inline fun DoubleField.nd(vararg shape: Int, action: DoubleFieldND.() -> R): R { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } - return RealFieldND(shape).run(action) + return DoubleFieldND(shape).run(action) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt index 4841e78d6..0101b058a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt @@ -55,7 +55,7 @@ public interface ExtendedField : ExtendedFieldOperations, Field, Numeri * A field for [Double] without boxing. Does not produce appropriate field element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public object RealField : ExtendedField, Norm, ScaleOperations { +public object DoubleField : ExtendedField, Norm, ScaleOperations { public override val zero: Double = 0.0 public override val one: Double = 1.0 diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 1d40a2f2e..1c64bfcec 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -53,14 +53,14 @@ public interface Buffer { /** * Creates a [Buffer] of given [type]. If the type is primitive, specialized buffers are used ([IntBuffer], - * [RealBuffer], etc.), [ListBuffer] is returned otherwise. + * [DoubleBuffer], etc.), [ListBuffer] is returned otherwise. * * The [size] is specified, and each element is calculated by calling the specified [initializer] function. */ @Suppress("UNCHECKED_CAST") public inline fun auto(type: KClass, size: Int, initializer: (Int) -> T): Buffer = when (type) { - Double::class -> MutableBuffer.real(size) { initializer(it) as Double } as Buffer + Double::class -> MutableBuffer.double(size) { initializer(it) as Double } as Buffer Short::class -> MutableBuffer.short(size) { initializer(it) as Short } as Buffer Int::class -> MutableBuffer.int(size) { initializer(it) as Int } as Buffer Long::class -> MutableBuffer.long(size) { initializer(it) as Long } as Buffer @@ -70,7 +70,7 @@ public interface Buffer { /** * Creates a [Buffer] of given type [T]. If the type is primitive, specialized buffers are used ([IntBuffer], - * [RealBuffer], etc.), [ListBuffer] is returned otherwise. + * [DoubleBuffer], etc.), [ListBuffer] is returned otherwise. * * The [size] is specified, and each element is calculated by calling the specified [initializer] function. */ @@ -104,11 +104,11 @@ public interface MutableBuffer : Buffer { public companion object { /** - * Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified + * Creates a [DoubleBuffer] with the specified [size], where each element is calculated by calling the specified * [initializer] function. */ - public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer = - RealBuffer(size, initializer) + public inline fun double(size: Int, initializer: (Int) -> Double): DoubleBuffer = + DoubleBuffer(size, initializer) /** * Creates a [ShortBuffer] with the specified [size], where each element is calculated by calling the specified @@ -148,14 +148,14 @@ public interface MutableBuffer : Buffer { /** * Creates a [MutableBuffer] of given [type]. If the type is primitive, specialized buffers are used - * ([IntBuffer], [RealBuffer], etc.), [ListBuffer] is returned otherwise. + * ([IntBuffer], [DoubleBuffer], etc.), [ListBuffer] is returned otherwise. * * The [size] is specified, and each element is calculated by calling the specified [initializer] function. */ @Suppress("UNCHECKED_CAST") public inline fun auto(type: KClass, size: Int, initializer: (Int) -> T): MutableBuffer = when (type) { - Double::class -> real(size) { initializer(it) as Double } as MutableBuffer + Double::class -> double(size) { initializer(it) as Double } as MutableBuffer Short::class -> short(size) { initializer(it) as Short } as MutableBuffer Int::class -> int(size) { initializer(it) as Int } as MutableBuffer Float::class -> float(size) { initializer(it) as Float } as MutableBuffer @@ -165,7 +165,7 @@ public interface MutableBuffer : Buffer { /** * Creates a [MutableBuffer] of given type [T]. If the type is primitive, specialized buffers are used - * ([IntBuffer], [RealBuffer], etc.), [ListBuffer] is returned otherwise. + * ([IntBuffer], [DoubleBuffer], etc.), [ListBuffer] is returned otherwise. * * The [size] is specified, and each element is calculated by calling the specified [initializer] function. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt similarity index 53% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt index b56c03b76..0a23d31fe 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.structures * @property array the underlying array. */ @Suppress("OVERRIDE_BY_INLINE") -public inline class RealBuffer(public val array: DoubleArray) : MutableBuffer { +public inline class DoubleBuffer(public val array: DoubleArray) : MutableBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Double = array[index] @@ -17,40 +17,40 @@ public inline class RealBuffer(public val array: DoubleArray) : MutableBuffer Double): RealBuffer = RealBuffer(DoubleArray(size) { init(it) }) +public inline fun DoubleBuffer(size: Int, init: (Int) -> Double): DoubleBuffer = DoubleBuffer(DoubleArray(size) { init(it) }) /** - * Returns a new [RealBuffer] of given elements. + * Returns a new [DoubleBuffer] of given elements. */ -public fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles) +public fun DoubleBuffer(vararg doubles: Double): DoubleBuffer = DoubleBuffer(doubles) /** - * Simplified [RealBuffer] to array comparison + * Simplified [DoubleBuffer] to array comparison */ -public fun RealBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles) +public fun DoubleBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles) /** * Returns a new [DoubleArray] containing all of the elements of this [Buffer]. */ public fun Buffer.toDoubleArray(): DoubleArray = when (this) { - is RealBuffer -> array.copyOf() + is DoubleBuffer -> array.copyOf() else -> DoubleArray(size, ::get) } /** - * Returns [RealBuffer] over this array. + * Returns [DoubleBuffer] over this array. * * @receiver the array. * @return the new buffer. */ -public fun DoubleArray.asBuffer(): RealBuffer = RealBuffer(this) +public fun DoubleArray.asBuffer(): DoubleBuffer = DoubleBuffer(this) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBufferField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBufferField.kt new file mode 100644 index 000000000..4a85219ac --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBufferField.kt @@ -0,0 +1,272 @@ +package space.kscience.kmath.structures + +import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.operations.ExtendedFieldOperations +import kotlin.math.* + +/** + * [ExtendedFieldOperations] over [DoubleBuffer]. + */ +public object DoubleBufferFieldOperations : ExtendedFieldOperations> { + override fun Buffer.unaryMinus(): DoubleBuffer = if (this is DoubleBuffer) { + DoubleBuffer(size) { -array[it] } + } else { + DoubleBuffer(size) { -get(it) } + } + + public override fun add(a: Buffer, b: Buffer): DoubleBuffer { + require(b.size == a.size) { + "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " + } + + return if (a is DoubleBuffer && b is DoubleBuffer) { + val aArray = a.array + val bArray = b.array + DoubleBuffer(DoubleArray(a.size) { aArray[it] + bArray[it] }) + } else DoubleBuffer(DoubleArray(a.size) { a[it] + b[it] }) + } +// +// public override fun multiply(a: Buffer, k: Number): RealBuffer { +// val kValue = k.toDouble() +// +// return if (a is RealBuffer) { +// val aArray = a.array +// RealBuffer(DoubleArray(a.size) { aArray[it] * kValue }) +// } else RealBuffer(DoubleArray(a.size) { a[it] * kValue }) +// } +// +// public override fun divide(a: Buffer, k: Number): RealBuffer { +// val kValue = k.toDouble() +// +// return if (a is RealBuffer) { +// val aArray = a.array +// RealBuffer(DoubleArray(a.size) { aArray[it] / kValue }) +// } else RealBuffer(DoubleArray(a.size) { a[it] / kValue }) +// } + + public override fun multiply(a: Buffer, b: Buffer): DoubleBuffer { + require(b.size == a.size) { + "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " + } + + return if (a is DoubleBuffer && b is DoubleBuffer) { + val aArray = a.array + val bArray = b.array + DoubleBuffer(DoubleArray(a.size) { aArray[it] * bArray[it] }) + } else + DoubleBuffer(DoubleArray(a.size) { a[it] * b[it] }) + } + + public override fun divide(a: Buffer, b: Buffer): DoubleBuffer { + require(b.size == a.size) { + "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " + } + + return if (a is DoubleBuffer && b is DoubleBuffer) { + val aArray = a.array + val bArray = b.array + DoubleBuffer(DoubleArray(a.size) { aArray[it] / bArray[it] }) + } else DoubleBuffer(DoubleArray(a.size) { a[it] / b[it] }) + } + + public override fun sin(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { sin(array[it]) }) + } else DoubleBuffer(DoubleArray(arg.size) { sin(arg[it]) }) + + public override fun cos(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { cos(array[it]) }) + } else DoubleBuffer(DoubleArray(arg.size) { cos(arg[it]) }) + + public override fun tan(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { tan(array[it]) }) + } else DoubleBuffer(DoubleArray(arg.size) { tan(arg[it]) }) + + public override fun asin(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { asin(array[it]) }) + } else + DoubleBuffer(DoubleArray(arg.size) { asin(arg[it]) }) + + public override fun acos(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { acos(array[it]) }) + } else + DoubleBuffer(DoubleArray(arg.size) { acos(arg[it]) }) + + public override fun atan(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { atan(array[it]) }) + } else + DoubleBuffer(DoubleArray(arg.size) { atan(arg[it]) }) + + public override fun sinh(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { sinh(array[it]) }) + } else + DoubleBuffer(DoubleArray(arg.size) { sinh(arg[it]) }) + + public override fun cosh(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { cosh(array[it]) }) + } else + DoubleBuffer(DoubleArray(arg.size) { cosh(arg[it]) }) + + public override fun tanh(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { tanh(array[it]) }) + } else + DoubleBuffer(DoubleArray(arg.size) { tanh(arg[it]) }) + + public override fun asinh(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { asinh(array[it]) }) + } else + DoubleBuffer(DoubleArray(arg.size) { asinh(arg[it]) }) + + public override fun acosh(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { acosh(array[it]) }) + } else + DoubleBuffer(DoubleArray(arg.size) { acosh(arg[it]) }) + + public override fun atanh(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { atanh(array[it]) }) + } else + DoubleBuffer(DoubleArray(arg.size) { atanh(arg[it]) }) + + public override fun power(arg: Buffer, pow: Number): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { array[it].pow(pow.toDouble()) }) + } else + DoubleBuffer(DoubleArray(arg.size) { arg[it].pow(pow.toDouble()) }) + + public override fun exp(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { exp(array[it]) }) + } else DoubleBuffer(DoubleArray(arg.size) { exp(arg[it]) }) + + public override fun ln(arg: Buffer): DoubleBuffer = if (arg is DoubleBuffer) { + val array = arg.array + DoubleBuffer(DoubleArray(arg.size) { ln(array[it]) }) + } else + DoubleBuffer(DoubleArray(arg.size) { ln(arg[it]) }) +} + +/** + * [ExtendedField] over [DoubleBuffer]. + * + * @property size the size of buffers to operate on. + */ +public class DoubleBufferField(public val size: Int) : ExtendedField> { + public override val zero: Buffer by lazy { DoubleBuffer(size) { 0.0 } } + public override val one: Buffer by lazy { DoubleBuffer(size) { 1.0 } } + + override fun number(value: Number): Buffer = DoubleBuffer(size) { value.toDouble() } + + override fun Buffer.unaryMinus(): Buffer = DoubleBufferFieldOperations.run { + -this@unaryMinus + } + + public override fun add(a: Buffer, b: Buffer): DoubleBuffer { + require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } + return DoubleBufferFieldOperations.add(a, b) + } + + public override fun scale(a: Buffer, value: Double): DoubleBuffer { + require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } + + return if (a is DoubleBuffer) { + val aArray = a.array + DoubleBuffer(DoubleArray(a.size) { aArray[it] * value }) + } else DoubleBuffer(DoubleArray(a.size) { a[it] * value }) + } + + public override fun multiply(a: Buffer, b: Buffer): DoubleBuffer { + require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } + return DoubleBufferFieldOperations.multiply(a, b) + } + + public override fun divide(a: Buffer, b: Buffer): DoubleBuffer { + require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } + return DoubleBufferFieldOperations.divide(a, b) + } + + public override fun sin(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.sin(arg) + } + + public override fun cos(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.cos(arg) + } + + public override fun tan(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.tan(arg) + } + + public override fun asin(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.asin(arg) + } + + public override fun acos(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.acos(arg) + } + + public override fun atan(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.atan(arg) + } + + public override fun sinh(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.sinh(arg) + } + + public override fun cosh(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.cosh(arg) + } + + public override fun tanh(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.tanh(arg) + } + + public override fun asinh(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.asinh(arg) + } + + public override fun acosh(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.acosh(arg) + } + + public override fun atanh(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.atanh(arg) + } + + public override fun power(arg: Buffer, pow: Number): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.power(arg, pow) + } + + public override fun exp(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.exp(arg) + } + + public override fun ln(arg: Buffer): DoubleBuffer { + require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } + return DoubleBufferFieldOperations.ln(arg) + } +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt index 3326c1491..670a0c175 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt @@ -48,7 +48,7 @@ public fun FlaggedBuffer<*>.isMissing(index: Int): Boolean = hasFlag(index, Valu /** * A real buffer which supports flags for each value like NaN or Missing */ -public class FlaggedRealBuffer(public val values: DoubleArray, public val flags: ByteArray) : FlaggedBuffer, +public class FlaggedDoubleBuffer(public val values: DoubleArray, public val flags: ByteArray) : FlaggedBuffer, Buffer { init { require(values.size == flags.size) { "Values and flags must have the same dimensions" } @@ -65,7 +65,7 @@ public class FlaggedRealBuffer(public val values: DoubleArray, public val flags: }.iterator() } -public inline fun FlaggedRealBuffer.forEachValid(block: (Double) -> Unit) { +public inline fun FlaggedDoubleBuffer.forEachValid(block: (Double) -> Unit) { indices .asSequence() .filter(::isValid) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt deleted file mode 100644 index 2a03a36e3..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt +++ /dev/null @@ -1,272 +0,0 @@ -package space.kscience.kmath.structures - -import space.kscience.kmath.operations.ExtendedField -import space.kscience.kmath.operations.ExtendedFieldOperations -import kotlin.math.* - -/** - * [ExtendedFieldOperations] over [RealBuffer]. - */ -public object RealBufferFieldOperations : ExtendedFieldOperations> { - override fun Buffer.unaryMinus(): RealBuffer = if (this is RealBuffer) { - RealBuffer(size) { -array[it] } - } else { - RealBuffer(size) { -get(it) } - } - - public override fun add(a: Buffer, b: Buffer): RealBuffer { - require(b.size == a.size) { - "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " - } - - return if (a is RealBuffer && b is RealBuffer) { - val aArray = a.array - val bArray = b.array - RealBuffer(DoubleArray(a.size) { aArray[it] + bArray[it] }) - } else RealBuffer(DoubleArray(a.size) { a[it] + b[it] }) - } -// -// public override fun multiply(a: Buffer, k: Number): RealBuffer { -// val kValue = k.toDouble() -// -// return if (a is RealBuffer) { -// val aArray = a.array -// RealBuffer(DoubleArray(a.size) { aArray[it] * kValue }) -// } else RealBuffer(DoubleArray(a.size) { a[it] * kValue }) -// } -// -// public override fun divide(a: Buffer, k: Number): RealBuffer { -// val kValue = k.toDouble() -// -// return if (a is RealBuffer) { -// val aArray = a.array -// RealBuffer(DoubleArray(a.size) { aArray[it] / kValue }) -// } else RealBuffer(DoubleArray(a.size) { a[it] / kValue }) -// } - - public override fun multiply(a: Buffer, b: Buffer): RealBuffer { - require(b.size == a.size) { - "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " - } - - return if (a is RealBuffer && b is RealBuffer) { - val aArray = a.array - val bArray = b.array - RealBuffer(DoubleArray(a.size) { aArray[it] * bArray[it] }) - } else - RealBuffer(DoubleArray(a.size) { a[it] * b[it] }) - } - - public override fun divide(a: Buffer, b: Buffer): RealBuffer { - require(b.size == a.size) { - "The size of the first buffer ${a.size} should be the same as for second one: ${b.size} " - } - - return if (a is RealBuffer && b is RealBuffer) { - val aArray = a.array - val bArray = b.array - RealBuffer(DoubleArray(a.size) { aArray[it] / bArray[it] }) - } else RealBuffer(DoubleArray(a.size) { a[it] / b[it] }) - } - - public override fun sin(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { sin(array[it]) }) - } else RealBuffer(DoubleArray(arg.size) { sin(arg[it]) }) - - public override fun cos(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { cos(array[it]) }) - } else RealBuffer(DoubleArray(arg.size) { cos(arg[it]) }) - - public override fun tan(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { tan(array[it]) }) - } else RealBuffer(DoubleArray(arg.size) { tan(arg[it]) }) - - public override fun asin(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { asin(array[it]) }) - } else - RealBuffer(DoubleArray(arg.size) { asin(arg[it]) }) - - public override fun acos(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { acos(array[it]) }) - } else - RealBuffer(DoubleArray(arg.size) { acos(arg[it]) }) - - public override fun atan(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { atan(array[it]) }) - } else - RealBuffer(DoubleArray(arg.size) { atan(arg[it]) }) - - public override fun sinh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { sinh(array[it]) }) - } else - RealBuffer(DoubleArray(arg.size) { sinh(arg[it]) }) - - public override fun cosh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { cosh(array[it]) }) - } else - RealBuffer(DoubleArray(arg.size) { cosh(arg[it]) }) - - public override fun tanh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { tanh(array[it]) }) - } else - RealBuffer(DoubleArray(arg.size) { tanh(arg[it]) }) - - public override fun asinh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { asinh(array[it]) }) - } else - RealBuffer(DoubleArray(arg.size) { asinh(arg[it]) }) - - public override fun acosh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { acosh(array[it]) }) - } else - RealBuffer(DoubleArray(arg.size) { acosh(arg[it]) }) - - public override fun atanh(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { atanh(array[it]) }) - } else - RealBuffer(DoubleArray(arg.size) { atanh(arg[it]) }) - - public override fun power(arg: Buffer, pow: Number): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { array[it].pow(pow.toDouble()) }) - } else - RealBuffer(DoubleArray(arg.size) { arg[it].pow(pow.toDouble()) }) - - public override fun exp(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { exp(array[it]) }) - } else RealBuffer(DoubleArray(arg.size) { exp(arg[it]) }) - - public override fun ln(arg: Buffer): RealBuffer = if (arg is RealBuffer) { - val array = arg.array - RealBuffer(DoubleArray(arg.size) { ln(array[it]) }) - } else - RealBuffer(DoubleArray(arg.size) { ln(arg[it]) }) -} - -/** - * [ExtendedField] over [RealBuffer]. - * - * @property size the size of buffers to operate on. - */ -public class RealBufferField(public val size: Int) : ExtendedField> { - public override val zero: Buffer by lazy { RealBuffer(size) { 0.0 } } - public override val one: Buffer by lazy { RealBuffer(size) { 1.0 } } - - override fun number(value: Number): Buffer = RealBuffer(size) { value.toDouble() } - - override fun Buffer.unaryMinus(): Buffer = RealBufferFieldOperations.run { - -this@unaryMinus - } - - public override fun add(a: Buffer, b: Buffer): RealBuffer { - require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } - return RealBufferFieldOperations.add(a, b) - } - - public override fun scale(a: Buffer, value: Double): RealBuffer { - require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } - - return if (a is RealBuffer) { - val aArray = a.array - RealBuffer(DoubleArray(a.size) { aArray[it] * value }) - } else RealBuffer(DoubleArray(a.size) { a[it] * value }) - } - - public override fun multiply(a: Buffer, b: Buffer): RealBuffer { - require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } - return RealBufferFieldOperations.multiply(a, b) - } - - public override fun divide(a: Buffer, b: Buffer): RealBuffer { - require(a.size == size) { "The buffer size ${a.size} does not match context size $size" } - return RealBufferFieldOperations.divide(a, b) - } - - public override fun sin(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.sin(arg) - } - - public override fun cos(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.cos(arg) - } - - public override fun tan(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.tan(arg) - } - - public override fun asin(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.asin(arg) - } - - public override fun acos(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.acos(arg) - } - - public override fun atan(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.atan(arg) - } - - public override fun sinh(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.sinh(arg) - } - - public override fun cosh(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.cosh(arg) - } - - public override fun tanh(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.tanh(arg) - } - - public override fun asinh(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.asinh(arg) - } - - public override fun acosh(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.acosh(arg) - } - - public override fun atanh(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.atanh(arg) - } - - public override fun power(arg: Buffer, pow: Number): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.power(arg, pow) - } - - public override fun exp(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.exp(arg) - } - - public override fun ln(arg: Buffer): RealBuffer { - require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" } - return RealBufferFieldOperations.ln(arg) - } -} diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt index cf75eba3e..b1be0c392 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals @@ -11,7 +11,7 @@ class ExpressionFieldTest { @Test fun testExpression() { - val expression = FunctionalExpressionField(RealField).invoke { + val expression = FunctionalExpressionField(DoubleField).invoke { val x by binding() x * x + 2 * x + one } @@ -27,7 +27,7 @@ class ExpressionFieldTest { return x * x + 2 * x + one } - val expression = FunctionalExpressionField(RealField).expression() + val expression = FunctionalExpressionField(DoubleField).expression() assertEquals(expression(x to 1.0), 4.0) } @@ -38,7 +38,7 @@ class ExpressionFieldTest { x * x + 2 * x + one } - val expression = FunctionalExpressionField(RealField).expressionBuilder() + val expression = FunctionalExpressionField(DoubleField).expressionBuilder() assertEquals(expression(x to 1.0), 4.0) } } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt index ee7fffa4c..95b2b2d1c 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.asBuffer import kotlin.math.E import kotlin.math.PI @@ -14,19 +14,19 @@ class SimpleAutoDiffTest { fun dx( xBinding: Pair, - body: SimpleAutoDiffField.(x: AutoDiffValue) -> AutoDiffValue, - ): DerivationResult = RealField.simpleAutoDiff(xBinding) { body(bindSymbol(xBinding.first)) } + body: SimpleAutoDiffField.(x: AutoDiffValue) -> AutoDiffValue, + ): DerivationResult = DoubleField.simpleAutoDiff(xBinding) { body(bindSymbol(xBinding.first)) } fun dxy( xBinding: Pair, yBinding: Pair, - body: SimpleAutoDiffField.(x: AutoDiffValue, y: AutoDiffValue) -> AutoDiffValue, - ): DerivationResult = RealField.simpleAutoDiff(xBinding, yBinding) { + body: SimpleAutoDiffField.(x: AutoDiffValue, y: AutoDiffValue) -> AutoDiffValue, + ): DerivationResult = DoubleField.simpleAutoDiff(xBinding, yBinding) { body(bindSymbol(xBinding.first), bindSymbol(yBinding.first)) } - fun diff(block: SimpleAutoDiffField.() -> AutoDiffValue): SimpleAutoDiffExpression { - return SimpleAutoDiffExpression(RealField, block) + fun diff(block: SimpleAutoDiffField.() -> AutoDiffValue): SimpleAutoDiffExpression { + return SimpleAutoDiffExpression(DoubleField, block) } val x by symbol @@ -35,7 +35,7 @@ class SimpleAutoDiffTest { @Test fun testPlusX2() { - val y = RealField.simpleAutoDiff(x to 3.0) { + val y = DoubleField.simpleAutoDiff(x to 3.0) { // diff w.r.t this x at 3 val x = bindSymbol(x) x + x @@ -58,7 +58,7 @@ class SimpleAutoDiffTest { @Test fun testPlus() { // two variables - val z = RealField.simpleAutoDiff(x to 2.0, y to 3.0) { + val z = DoubleField.simpleAutoDiff(x to 2.0, y to 3.0) { val x = bindSymbol(x) val y = bindSymbol(y) x + y @@ -71,7 +71,7 @@ class SimpleAutoDiffTest { @Test fun testMinus() { // two variables - val z = RealField.simpleAutoDiff(x to 7.0, y to 3.0) { + val z = DoubleField.simpleAutoDiff(x to 7.0, y to 3.0) { val x = bindSymbol(x) val y = bindSymbol(y) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt similarity index 97% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt rename to kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt index e6efc6a8a..6761575f6 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt @@ -5,7 +5,7 @@ import kotlin.test.Test import kotlin.test.assertEquals @UnstableKMathAPI -class RealLUSolverTest { +class DoubleLUSolverTest { @Test fun testInvertOne() { diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/RealFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt similarity index 59% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/RealFieldTest.kt rename to kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt index bba612d12..fde4f4a9e 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/RealFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt @@ -4,13 +4,13 @@ import space.kscience.kmath.testutils.FieldVerifier import kotlin.test.Test import kotlin.test.assertEquals -internal class RealFieldTest { +internal class DoubleFieldTest { @Test - fun verify() = FieldVerifier(RealField, 42.0, 66.0, 2.0, 5).verify() + fun verify() = FieldVerifier(DoubleField, 42.0, 66.0, 2.0, 5).verify() @Test fun testSqrt() { - val sqrt = RealField { sqrt(25 * one) } + val sqrt = DoubleField { sqrt(25 * one) } assertEquals(5.0, sqrt) } } diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingRealChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt similarity index 82% rename from kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingRealChain.kt rename to kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt index ac6b117dc..bc4508994 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingRealChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt @@ -3,7 +3,7 @@ package space.kscience.kmath.chains /** * Performance optimized chain for real values */ -public abstract class BlockingRealChain : Chain { +public abstract class BlockingDoubleChain : Chain { public abstract fun nextDouble(): Double override suspend fun next(): Double = nextDouble() diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt index 4df22c2ad..c271f8889 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt @@ -2,10 +2,10 @@ package space.kscience.kmath.streaming import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.* -import space.kscience.kmath.chains.BlockingRealChain +import space.kscience.kmath.chains.BlockingDoubleChain import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer /** @@ -45,10 +45,10 @@ public fun Flow.chunked(bufferSize: Int, bufferFactory: BufferFactory) /** * Specialized flow chunker for real buffer */ -public fun Flow.chunked(bufferSize: Int): Flow = flow { +public fun Flow.chunked(bufferSize: Int): Flow = flow { require(bufferSize > 0) { "Resulting chunk size must be more than zero" } - if (this@chunked is BlockingRealChain) { + if (this@chunked is BlockingDoubleChain) { // performance optimization for blocking primitive chain while (true) emit(nextBlock(bufferSize).asBuffer()) } else { @@ -60,13 +60,13 @@ public fun Flow.chunked(bufferSize: Int): Flow = flow { counter++ if (counter == bufferSize) { - val buffer = RealBuffer(array) + val buffer = DoubleBuffer(array) emit(buffer) counter = 0 } } - if (counter > 0) emit(RealBuffer(counter) { array[it] }) + if (counter > 0) emit(DoubleBuffer(counter) { array[it] }) } } diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt index 468b90561..261f91aee 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt @@ -10,7 +10,7 @@ public class LazyStructureND( public override val shape: IntArray, public val function: suspend (IntArray) -> T, ) : StructureND { - private val cache: MutableMap> = hashMapOf() + private val cache: MutableMap> = HashMap() public fun deferred(index: IntArray): Deferred = cache.getOrPut(index) { scope.async(context = Dispatchers.Math) { function(index) } diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt index 81b008b6a..dd85a97cb 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt @@ -5,7 +5,7 @@ import space.kscience.kmath.linear.Matrix import space.kscience.kmath.linear.Point import space.kscience.kmath.linear.transpose import space.kscience.kmath.nd.Structure2D -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Ring /** @@ -142,7 +142,7 @@ public inline class DMatrixContext>(public val context: context.run { (this@transpose as Matrix).transpose() }.coerce() public companion object { - public val real: DMatrixContext = DMatrixContext(LinearSpace.real) + public val real: DMatrixContext = DMatrixContext(LinearSpace.real) } } @@ -150,12 +150,12 @@ public inline class DMatrixContext>(public val context: /** * A square unit matrix */ -public inline fun DMatrixContext.one(): DMatrix = +public inline fun DMatrixContext.one(): DMatrix = produce { i, j -> if (i == j) 1.0 else 0.0 } -public inline fun DMatrixContext.zero(): DMatrix = +public inline fun DMatrixContext.zero(): DMatrix = produce { _, _ -> 0.0 } \ No newline at end of file diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index 452280295..a82fe933e 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -5,8 +5,8 @@ import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.getFeature -import space.kscience.kmath.operations.RealField -import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.structures.DoubleBuffer import kotlin.reflect.KClass import kotlin.reflect.cast @@ -15,9 +15,9 @@ import kotlin.reflect.cast * * @author Iaroslav Postovalov */ -public object EjmlLinearSpace : LinearSpace { +public object EjmlLinearSpace : LinearSpace { - override val elementAlgebra: RealField get() = RealField + override val elementAlgebra: DoubleField get() = DoubleField /** * Converts this matrix to EJML one. @@ -38,16 +38,16 @@ public object EjmlLinearSpace : LinearSpace { }) } - override fun buildMatrix(rows: Int, columns: Int, initializer: RealField.(i: Int, j: Int) -> Double): EjmlMatrix = + override fun buildMatrix(rows: Int, columns: Int, initializer: DoubleField.(i: Int, j: Int) -> Double): EjmlMatrix = EjmlMatrix(SimpleMatrix(rows, columns).also { (0 until rows).forEach { row -> - (0 until columns).forEach { col -> it[row, col] = RealField.initializer(row, col) } + (0 until columns).forEach { col -> it[row, col] = DoubleField.initializer(row, col) } } }) - override fun buildVector(size: Int, initializer: RealField.(Int) -> Double): Point = + override fun buildVector(size: Int, initializer: DoubleField.(Int) -> Double): Point = EjmlVector(SimpleMatrix(size, 1).also { - (0 until it.numRows()).forEach { row -> it[row, 0] = RealField.initializer(row) } + (0 until it.numRows()).forEach { row -> it[row, 0] = DoubleField.initializer(row) } }) private fun SimpleMatrix.wrapMatrix() = EjmlMatrix(this) @@ -113,7 +113,7 @@ public object EjmlLinearSpace : LinearSpace { override val u: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getU(null, false))) } override val s: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getW(null))) } override val v: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getV(null, false))) } - override val singularValues: Point by lazy { RealBuffer(svd.singularValues) } + override val singularValues: Point by lazy { DoubleBuffer(svd.singularValues) } } QRDecompositionFeature::class -> object : QRDecompositionFeature { diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index d095cac04..5fc6724f3 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -18,15 +18,15 @@ readme { propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( - id = "RealVector", + id = "DoubleVector", description = "Numpy-like operations for Buffers/Points", - ref = "src/commonMain/kotlin/kscience/kmath/real/RealVector.kt" + ref = "src/commonMain/kotlin/kscience/kmath/real/DoubleVector.kt" ) feature( - id = "RealMatrix", + id = "DoubleMatrix", description = "Numpy-like operations for 2d real structures", - ref = "src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt" + ref = "src/commonMain/kotlin/kscience/kmath/real/DoubleMatrix.kt" ) feature( diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt index 76c73ab16..a16d64234 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt @@ -2,9 +2,9 @@ package space.kscience.kmath.real import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asIterable import kotlin.math.pow @@ -22,11 +22,11 @@ import kotlin.math.pow public typealias RealMatrix = Matrix -public fun realMatrix(rowNum: Int, colNum: Int, initializer: RealField.(i: Int, j: Int) -> Double): RealMatrix = +public fun realMatrix(rowNum: Int, colNum: Int, initializer: DoubleField.(i: Int, j: Int) -> Double): RealMatrix = LinearSpace.real.buildMatrix(rowNum, colNum, initializer) @OptIn(UnstableKMathAPI::class) -public fun realMatrix(rowNum: Int, colNum: Int): MatrixBuilder = +public fun realMatrix(rowNum: Int, colNum: Int): MatrixBuilder = LinearSpace.real.matrix(rowNum, colNum) public fun Array.toMatrix(): RealMatrix { @@ -120,19 +120,19 @@ public fun RealMatrix.extractColumns(columnRange: IntRange): RealMatrix = public fun RealMatrix.extractColumn(columnIndex: Int): RealMatrix = extractColumns(columnIndex..columnIndex) -public fun RealMatrix.sumByColumn(): RealBuffer = RealBuffer(colNum) { j -> +public fun RealMatrix.sumByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j -> columns[j].asIterable().sum() } -public fun RealMatrix.minByColumn(): RealBuffer = RealBuffer(colNum) { j -> +public fun RealMatrix.minByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j -> columns[j].asIterable().minOrNull() ?: error("Cannot produce min on empty column") } -public fun RealMatrix.maxByColumn(): RealBuffer = RealBuffer(colNum) { j -> +public fun RealMatrix.maxByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j -> columns[j].asIterable().maxOrNull() ?: error("Cannot produce min on empty column") } -public fun RealMatrix.averageByColumn(): RealBuffer = RealBuffer(colNum) { j -> +public fun RealMatrix.averageByColumn(): DoubleBuffer = DoubleBuffer(colNum) { j -> columns[j].asIterable().average() } diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt index 8cc128947..433e3c756 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt @@ -4,98 +4,99 @@ import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Norm import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.MutableBuffer.Companion.real +import space.kscience.kmath.structures.MutableBuffer.Companion.double import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.asIterable import space.kscience.kmath.structures.indices import kotlin.math.pow import kotlin.math.sqrt -public typealias RealVector = Point +public typealias DoubleVector = Point public object VectorL2Norm : Norm, Double> { override fun norm(arg: Point): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble)) } -public operator fun Buffer.Companion.invoke(vararg doubles: Double): RealVector = doubles.asBuffer() +@Suppress("FunctionName") +public fun DoubleVector(vararg doubles: Double): DoubleVector = doubles.asBuffer() /** * Fill the vector of given [size] with given [value] */ @UnstableKMathAPI -public fun Buffer.Companion.same(size: Int, value: Number): RealVector = real(size) { value.toDouble() } +public fun Buffer.Companion.same(size: Int, value: Number): DoubleVector = double(size) { value.toDouble() } // Transformation methods -public inline fun RealVector.map(transform: (Double) -> Double): RealVector = - real(size) { transform(get(it)) } +public inline fun DoubleVector.map(transform: (Double) -> Double): DoubleVector = + double(size) { transform(get(it)) } -public inline fun RealVector.mapIndexed(transform: (index: Int, value: Double) -> Double): RealVector = - real(size) { transform(it, get(it)) } +public inline fun DoubleVector.mapIndexed(transform: (index: Int, value: Double) -> Double): DoubleVector = + double(size) { transform(it, get(it)) } -public operator fun RealVector.plus(other: RealVector): RealVector { +public operator fun DoubleVector.plus(other: DoubleVector): DoubleVector { require(size == other.size) { "Vector size $size expected but ${other.size} found" } return mapIndexed { index, value -> value + other[index] } } -public operator fun RealVector.plus(number: Number): RealVector = map { it + number.toDouble() } +public operator fun DoubleVector.plus(number: Number): DoubleVector = map { it + number.toDouble() } -public operator fun Number.plus(vector: RealVector): RealVector = vector + this +public operator fun Number.plus(vector: DoubleVector): DoubleVector = vector + this -public operator fun RealVector.unaryMinus(): Buffer = map { -it } +public operator fun DoubleVector.unaryMinus(): Buffer = map { -it } -public operator fun RealVector.minus(other: RealVector): RealVector { +public operator fun DoubleVector.minus(other: DoubleVector): DoubleVector { require(size == other.size) { "Vector size $size expected but ${other.size} found" } return mapIndexed { index, value -> value - other[index] } } -public operator fun RealVector.minus(number: Number): RealVector = map { it - number.toDouble() } +public operator fun DoubleVector.minus(number: Number): DoubleVector = map { it - number.toDouble() } -public operator fun Number.minus(vector: RealVector): RealVector = vector.map { toDouble() - it } +public operator fun Number.minus(vector: DoubleVector): DoubleVector = vector.map { toDouble() - it } -public operator fun RealVector.times(other: RealVector): RealVector { +public operator fun DoubleVector.times(other: DoubleVector): DoubleVector { require(size == other.size) { "Vector size $size expected but ${other.size} found" } return mapIndexed { index, value -> value * other[index] } } -public operator fun RealVector.times(number: Number): RealVector = map { it * number.toDouble() } +public operator fun DoubleVector.times(number: Number): DoubleVector = map { it * number.toDouble() } -public operator fun Number.times(vector: RealVector): RealVector = vector * this +public operator fun Number.times(vector: DoubleVector): DoubleVector = vector * this -public operator fun RealVector.div(other: RealVector): RealVector { +public operator fun DoubleVector.div(other: DoubleVector): DoubleVector { require(size == other.size) { "Vector size $size expected but ${other.size} found" } return mapIndexed { index, value -> value / other[index] } } -public operator fun RealVector.div(number: Number): RealVector = map { it / number.toDouble() } +public operator fun DoubleVector.div(number: Number): DoubleVector = map { it / number.toDouble() } -public operator fun Number.div(vector: RealVector): RealVector = vector.map { toDouble() / it } +public operator fun Number.div(vector: DoubleVector): DoubleVector = vector.map { toDouble() / it } //extended operations -public fun RealVector.pow(p: Double): RealVector = map { it.pow(p) } +public fun DoubleVector.pow(p: Double): DoubleVector = map { it.pow(p) } -public fun RealVector.pow(p: Int): RealVector = map { it.pow(p) } +public fun DoubleVector.pow(p: Int): DoubleVector = map { it.pow(p) } -public fun exp(vector: RealVector): RealVector = vector.map { kotlin.math.exp(it) } +public fun exp(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.exp(it) } -public fun sqrt(vector: RealVector): RealVector = vector.map { kotlin.math.sqrt(it) } +public fun sqrt(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.sqrt(it) } -public fun RealVector.square(): RealVector = map { it.pow(2) } +public fun DoubleVector.square(): DoubleVector = map { it.pow(2) } -public fun sin(vector: RealVector): RealVector = vector.map { kotlin.math.sin(it) } +public fun sin(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.sin(it) } -public fun cos(vector: RealVector): RealVector = vector.map { kotlin.math.cos(it) } +public fun cos(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.cos(it) } -public fun tan(vector: RealVector): RealVector = vector.map { kotlin.math.tan(it) } +public fun tan(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.tan(it) } -public fun ln(vector: RealVector): RealVector = vector.map { kotlin.math.ln(it) } +public fun ln(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.ln(it) } -public fun log10(vector: RealVector): RealVector = vector.map { kotlin.math.log10(it) } +public fun log10(vector: DoubleVector): DoubleVector = vector.map { kotlin.math.log10(it) } // reductions methods -public fun RealVector.sum(): Double { +public fun DoubleVector.sum(): Double { var res = 0.0 for (i in indices) { res += get(i) diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt index 8b4f1cd96..35297a3ac 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt @@ -33,7 +33,7 @@ public fun ClosedFloatingPointRange.toSequenceWithStep(step: Double): Se } } -public infix fun ClosedFloatingPointRange.step(step: Double): RealVector = +public infix fun ClosedFloatingPointRange.step(step: Double): DoubleVector = toSequenceWithStep(step).toList().asBuffer() /** diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt index 492e40922..7655a4170 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt @@ -1,15 +1,15 @@ package space.kscience.kmath.real import space.kscience.kmath.nd.NDBuffer -import space.kscience.kmath.operations.RealField -import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.structures.DoubleBuffer /** * Map one [NDBuffer] using function without indices. */ -public inline fun NDBuffer.mapInline(crossinline transform: RealField.(Double) -> Double): NDBuffer { - val array = DoubleArray(strides.linearSize) { offset -> RealField.transform(buffer[offset]) } - return NDBuffer(strides, RealBuffer(array)) +public inline fun NDBuffer.mapInline(crossinline transform: DoubleField.(Double) -> Double): NDBuffer { + val array = DoubleArray(strides.linearSize) { offset -> DoubleField.transform(buffer[offset]) } + return NDBuffer(strides, DoubleBuffer(array)) } /** diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt similarity index 99% rename from kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt rename to kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt index 06135598e..c1d3ccf5f 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt @@ -10,7 +10,7 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue @UnstableKMathAPI -internal class RealMatrixTest { +internal class DoubleMatrixTest { @Test fun testSum() { val m = realMatrix(10, 10) { i, j -> (i + j).toDouble() } diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleVectorTest.kt similarity index 67% rename from kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt rename to kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleVectorTest.kt index 60d85fda3..669f88186 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleVectorTest.kt @@ -4,30 +4,30 @@ import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.asMatrix import space.kscience.kmath.linear.transpose import space.kscience.kmath.real.plus -import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.structures.DoubleBuffer import kotlin.test.Test import kotlin.test.assertEquals -internal class RealVectorTest { +internal class DoubleVectorTest { @Test fun testSum() { - val vector1 = RealBuffer(5) { it.toDouble() } - val vector2 = RealBuffer(5) { 5 - it.toDouble() } + val vector1 = DoubleBuffer(5) { it.toDouble() } + val vector2 = DoubleBuffer(5) { 5 - it.toDouble() } val sum = vector1 + vector2 assertEquals(5.0, sum[2]) } @Test fun testVectorToMatrix() { - val vector = RealBuffer(5) { it.toDouble() } + val vector = DoubleBuffer(5) { it.toDouble() } val matrix = vector.asMatrix() assertEquals(4.0, matrix[4, 0]) } @Test fun testDot() { - val vector1 = RealBuffer(5) { it.toDouble() } - val vector2 = RealBuffer(5) { 5 - it.toDouble() } + val vector1 = DoubleBuffer(5) { it.toDouble() } + val vector2 = DoubleBuffer(5) { 5 - it.toDouble() } val matrix1 = vector1.asMatrix() val matrix2 = vector2.asMatrix().transpose() val product = LinearSpace.real.run { matrix1 dot matrix2 } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt index 0b7b62147..476c035e9 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.asFunction -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals @@ -16,8 +16,8 @@ internal class LinearInterpolatorTest { 3.0 to 4.0 ) - val polynomial: PiecewisePolynomial = LinearInterpolator(RealField).interpolatePolynomials(data) - val function = polynomial.asFunction(RealField) + val polynomial: PiecewisePolynomial = LinearInterpolator(DoubleField).interpolatePolynomials(data) + val function = polynomial.asFunction(DoubleField) assertEquals(null, function(-1.0)) assertEquals(0.5, function(0.5)) assertEquals(2.0, function(1.5)) diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt index ca0eba52f..616a72fde 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt @@ -2,8 +2,8 @@ package space.kscience.kmath.histogram import kotlinx.atomicfu.atomic import kotlinx.atomicfu.getAndUpdate +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Group -import space.kscience.kmath.operations.RealField /** * Common representation for atomic counters @@ -13,7 +13,7 @@ public interface Counter { public val value: T public companion object { - public fun real(): ObjectCounter = ObjectCounter(RealField) + public fun real(): ObjectCounter = ObjectCounter(DoubleField) } } diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/DoubleHistogramSpace.kt similarity index 92% rename from kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt rename to kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/DoubleHistogramSpace.kt index 1407470c1..fa9b67404 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/DoubleHistogramSpace.kt @@ -7,7 +7,7 @@ import space.kscience.kmath.nd.* import space.kscience.kmath.structures.* import kotlin.math.floor -public class RealHistogramSpace( +public class DoubleHistogramSpace( private val lower: Buffer, private val upper: Buffer, private val binNums: IntArray = IntArray(lower.size) { 20 }, @@ -23,10 +23,10 @@ public class RealHistogramSpace( public val dimension: Int get() = lower.size private val shape = IntArray(binNums.size) { binNums[it] + 2 } - override val histogramValueSpace: RealFieldND = AlgebraND.real(*shape) + override val histogramValueSpace: DoubleFieldND = AlgebraND.real(*shape) override val strides: Strides get() = histogramValueSpace.strides - private val binSize = RealBuffer(dimension) { (upper[it] - lower[it]) / binNums[it] } + private val binSize = DoubleBuffer(dimension) { (upper[it] - lower[it]) / binNums[it] } /** * Get internal [StructureND] bin index for given axis @@ -91,7 +91,7 @@ public class RealHistogramSpace( *) *``` */ - public fun fromRanges(vararg ranges: ClosedFloatingPointRange): RealHistogramSpace = RealHistogramSpace( + public fun fromRanges(vararg ranges: ClosedFloatingPointRange): DoubleHistogramSpace = DoubleHistogramSpace( ranges.map(ClosedFloatingPointRange::start).asBuffer(), ranges.map(ClosedFloatingPointRange::endInclusive).asBuffer() ) @@ -105,8 +105,8 @@ public class RealHistogramSpace( *) *``` */ - public fun fromRanges(vararg ranges: Pair, Int>): RealHistogramSpace = - RealHistogramSpace( + public fun fromRanges(vararg ranges: Pair, Int>): DoubleHistogramSpace = + DoubleHistogramSpace( ListBuffer( ranges .map(Pair, Int>::first) diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt index ed76c7aa1..d680a9ad0 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.Domain import space.kscience.kmath.linear.Point -import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer /** @@ -43,9 +43,9 @@ public fun > HistogramBuilder.put(point: Point): U public fun HistogramBuilder.put(vararg point: T): Unit = put(point.asBuffer()) public fun HistogramBuilder.put(vararg point: Number): Unit = - put(RealBuffer(point.map { it.toDouble() }.toDoubleArray())) + put(DoubleBuffer(point.map { it.toDouble() }.toDoubleArray())) -public fun HistogramBuilder.put(vararg point: Double): Unit = put(RealBuffer(point)) +public fun HistogramBuilder.put(vararg point: Double): Unit = put(DoubleBuffer(point)) public fun HistogramBuilder.fill(sequence: Iterable>): Unit = sequence.forEach { put(it) } /** diff --git a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt index fc00c6cdf..feb87a7a7 100644 --- a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt @@ -1,15 +1,14 @@ package space.kscience.kmath.histogram import space.kscience.kmath.operations.invoke -import space.kscience.kmath.real.RealVector -import space.kscience.kmath.real.invoke +import space.kscience.kmath.real.DoubleVector import kotlin.random.Random import kotlin.test.* internal class MultivariateHistogramTest { @Test fun testSinglePutHistogram() { - val hSpace = RealHistogramSpace.fromRanges( + val hSpace = DoubleHistogramSpace.fromRanges( (-1.0..1.0), (-1.0..1.0) ) @@ -17,14 +16,14 @@ internal class MultivariateHistogramTest { put(0.55, 0.55) } val bin = histogram.bins.find { it.value.toInt() > 0 } ?: fail() - assertTrue { bin.contains(RealVector(0.55, 0.55)) } - assertTrue { bin.contains(RealVector(0.6, 0.5)) } - assertFalse { bin.contains(RealVector(-0.55, 0.55)) } + assertTrue { bin.contains(DoubleVector(0.55, 0.55)) } + assertTrue { bin.contains(DoubleVector(0.6, 0.5)) } + assertFalse { bin.contains(DoubleVector(-0.55, 0.55)) } } @Test fun testSequentialPut() { - val hSpace = RealHistogramSpace.fromRanges( + val hSpace = DoubleHistogramSpace.fromRanges( (-1.0..1.0), (-1.0..1.0), (-1.0..1.0) @@ -44,7 +43,7 @@ internal class MultivariateHistogramTest { @Test fun testHistogramAlgebra() { - RealHistogramSpace.fromRanges( + DoubleHistogramSpace.fromRanges( (-1.0..1.0), (-1.0..1.0), (-1.0..1.0) diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index ffdabaffb..7cd3276b8 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -6,7 +6,7 @@ import space.kscience.kmath.ast.MstAlgebra import space.kscience.kmath.ast.MstExpression import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.operations.RealField +import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -16,8 +16,8 @@ internal class AdaptingTests { @Test fun symbol() { val c1 = MstAlgebra.bindSymbol("x") - assertTrue(c1.toSVar>().name == "x") - val c2 = "kitten".parseMath().toSFun>() + assertTrue(c1.toSVar>().name == "x") + val c2 = "kitten".parseMath().toSFun>() if (c2 is SVar) assertTrue(c2.name == "kitten") else fail() } @@ -25,15 +25,15 @@ internal class AdaptingTests { fun number() { val c1 = MstAlgebra.number(12354324) assertTrue(c1.toSConst().doubleValue == 12354324.0) - val c2 = "0.234".parseMath().toSFun>() + val c2 = "0.234".parseMath().toSFun>() if (c2 is SConst) assertTrue(c2.doubleValue == 0.234) else fail() - val c3 = "1e-3".parseMath().toSFun>() + val c3 = "1e-3".parseMath().toSFun>() if (c3 is SConst) assertEquals(0.001, c3.value) else fail() } @Test fun simpleFunctionShape() { - val linear = "2*x+16".parseMath().toSFun>() + val linear = "2*x+16".parseMath().toSFun>() if (linear !is Sum) fail() if (linear.left !is Prod) fail() if (linear.right !is SConst) fail() @@ -41,21 +41,21 @@ internal class AdaptingTests { @Test fun simpleFunctionDerivative() { - val x = MstAlgebra.bindSymbol("x").toSVar>() - val quadratic = "x^2-4*x-44".parseMath().toSFun>() - val actualDerivative = MstExpression(RealField, quadratic.d(x).toMst()).compile() - val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() + val x = MstAlgebra.bindSymbol("x").toSVar>() + val quadratic = "x^2-4*x-44".parseMath().toSFun>() + val actualDerivative = MstExpression(DoubleField, quadratic.d(x).toMst()).compile() + val expectedDerivative = MstExpression(DoubleField, "2*x-4".parseMath()).compile() assertEquals(actualDerivative("x" to 123.0), expectedDerivative("x" to 123.0)) } @Test fun moreComplexDerivative() { - val x = MstAlgebra.bindSymbol("x").toSVar>() - val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun>() - val actualDerivative = MstExpression(RealField, composition.d(x).toMst()).compile() + val x = MstAlgebra.bindSymbol("x").toSVar>() + val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun>() + val actualDerivative = MstExpression(DoubleField, composition.d(x).toMst()).compile() val expectedDerivative = MstExpression( - RealField, + DoubleField, "-(2*x*cos(x^2)+2*sin(x)*cos(x)-16)/(2*sqrt(sin(x^2)-16*x-cos(x)^2))".parseMath() ).compile() diff --git a/kmath-nd4j/docs/README-TEMPLATE.md b/kmath-nd4j/docs/README-TEMPLATE.md index 76ce8c9a7..9783e74be 100644 --- a/kmath-nd4j/docs/README-TEMPLATE.md +++ b/kmath-nd4j/docs/README-TEMPLATE.md @@ -15,7 +15,7 @@ import org.nd4j.linalg.factory.* import scientifik.kmath.nd4j.* import scientifik.kmath.structures.* -val array = Nd4j.ones(2, 2).asRealStructure() +val array = Nd4j.ones(2, 2).asDoubleStructure() println(array[0, 0]) // 1.0 array[intArrayOf(0, 0)] = 24.0 println(array[0, 0]) // 24.0 @@ -28,8 +28,8 @@ import org.nd4j.linalg.factory.* import scientifik.kmath.nd4j.* import scientifik.kmath.operations.* -val field = RealNd4jArrayField(intArrayOf(2, 2)) -val array = Nd4j.rand(2, 2).asRealStructure() +val field = DoubleNd4jArrayField(intArrayOf(2, 2)) +val array = Nd4j.rand(2, 2).asDoubleStructure() val res = field { (25.0 / array + 20) * 4 diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index bf73ec20f..8ea992bcb 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -172,7 +172,7 @@ public interface Nd4jArrayField> : FieldND, Nd4jArrayRing< private val floatNd4jArrayFieldCache: ThreadLocal> = ThreadLocal.withInitial { hashMapOf() } - private val realNd4jArrayFieldCache: ThreadLocal> = + private val doubleNd4JArrayFieldCache: ThreadLocal> = ThreadLocal.withInitial { hashMapOf() } /** @@ -184,8 +184,8 @@ public interface Nd4jArrayField> : FieldND, Nd4jArrayRing< /** * Creates an [FieldND] for [Double] values or pull it from cache if it was created previously. */ - public fun real(vararg shape: Int): Nd4jArrayRing = - realNd4jArrayFieldCache.get().getOrPut(shape) { RealNd4jArrayField(shape) } + public fun real(vararg shape: Int): Nd4jArrayRing = + doubleNd4JArrayFieldCache.get().getOrPut(shape) { DoubleNd4jArrayField(shape) } /** * Creates a most suitable implementation of [RingND] using reified class. @@ -200,12 +200,12 @@ public interface Nd4jArrayField> : FieldND, Nd4jArrayRing< } /** - * Represents [FieldND] over [Nd4jArrayRealStructure]. + * Represents [FieldND] over [Nd4jArrayDoubleStructure]. */ -public class RealNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField { - public override val elementContext: RealField get() = RealField +public class DoubleNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField { + public override val elementContext: DoubleField get() = DoubleField - public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asRealStructure() + public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asDoubleStructure() override fun scale(a: StructureND, value: Double): Nd4jArrayStructure { return a.ndArray.mul(value).wrap() diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt index 521c8cab3..cfb900277 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt @@ -37,11 +37,11 @@ private sealed class Nd4jArrayIteratorBase(protected val iterateOver: INDArra } } -private class Nd4jArrayRealIterator(iterateOver: INDArray) : Nd4jArrayIteratorBase(iterateOver) { +private class Nd4jArrayDoubleIterator(iterateOver: INDArray) : Nd4jArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray): Double = iterateOver.getDouble(*indices) } -internal fun INDArray.realIterator(): Iterator> = Nd4jArrayRealIterator(this) +internal fun INDArray.realIterator(): Iterator> = Nd4jArrayDoubleIterator(this) private class Nd4jArrayLongIterator(iterateOver: INDArray) : Nd4jArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray) = iterateOver.getLong(*indices) diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt index 9b4cc1a24..ec4cc9c56 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt @@ -45,7 +45,7 @@ private data class Nd4jArrayLongStructure(override val ndArray: INDArray) : Nd4j */ public fun INDArray.asLongStructure(): Nd4jArrayStructure = Nd4jArrayLongStructure(this) -private data class Nd4jArrayRealStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { +private data class Nd4jArrayDoubleStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { override fun elementsIterator(): Iterator> = ndArray.realIterator() override fun get(index: IntArray): Double = ndArray.getDouble(*index) override fun set(index: IntArray, value: Double): Unit = run { ndArray.putScalar(index, value) } @@ -54,7 +54,7 @@ private data class Nd4jArrayRealStructure(override val ndArray: INDArray) : Nd4j /** * Wraps this [INDArray] to [Nd4jArrayStructure]. */ -public fun INDArray.asRealStructure(): Nd4jArrayStructure = Nd4jArrayRealStructure(this) +public fun INDArray.asDoubleStructure(): Nd4jArrayStructure = Nd4jArrayDoubleStructure(this) private data class Nd4jArrayFloatStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { override fun elementsIterator(): Iterator> = ndArray.floatIterator() diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt index 6a8d8796c..e658275f5 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt @@ -8,8 +8,8 @@ import kotlin.test.fail internal class Nd4jArrayAlgebraTest { @Test fun testProduce() { - val res = with(RealNd4jArrayField(intArrayOf(2, 2))) { produce { it.sum().toDouble() } } - val expected = (Nd4j.create(2, 2) ?: fail()).asRealStructure() + val res = with(DoubleNd4jArrayField(intArrayOf(2, 2))) { produce { it.sum().toDouble() } } + val expected = (Nd4j.create(2, 2) ?: fail()).asDoubleStructure() expected[intArrayOf(0, 0)] = 0.0 expected[intArrayOf(0, 1)] = 1.0 expected[intArrayOf(1, 0)] = 1.0 diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt index 5cf6dd26f..0c03270dd 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt @@ -11,7 +11,7 @@ internal class Nd4jArrayStructureTest { @Test fun testElements() { val nd = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! - val struct = nd.asRealStructure() + val struct = nd.asDoubleStructure() val res = struct.elements().map(Pair::second).toList() assertEquals(listOf(1.0, 2.0, 3.0), res) } @@ -19,22 +19,22 @@ internal class Nd4jArrayStructureTest { @Test fun testShape() { val nd = Nd4j.rand(10, 2, 3, 6) ?: fail() - val struct = nd.asRealStructure() + val struct = nd.asDoubleStructure() assertEquals(intArrayOf(10, 2, 3, 6).toList(), struct.shape.toList()) } @Test fun testEquals() { val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail() - val struct1 = nd1.asRealStructure() + val struct1 = nd1.asDoubleStructure() assertEquals(struct1, struct1) assertNotEquals(struct1 as Any?, null) val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail() - val struct2 = nd2.asRealStructure() + val struct2 = nd2.asDoubleStructure() assertEquals(struct1, struct2) assertEquals(struct2, struct1) val nd3 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail() - val struct3 = nd3.asRealStructure() + val struct3 = nd3.asDoubleStructure() assertEquals(struct2, struct3) assertEquals(struct1, struct3) } @@ -42,9 +42,9 @@ internal class Nd4jArrayStructureTest { @Test fun testHashCode() { val nd1 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail() - val struct1 = nd1.asRealStructure() + val struct1 = nd1.asDoubleStructure() val nd2 = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0)) ?: fail() - val struct2 = nd2.asRealStructure() + val struct2 = nd2.asDoubleStructure() assertEquals(struct1.hashCode(), struct2.hashCode()) } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt index dacf7a9cd..25f6a87b5 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt @@ -4,7 +4,7 @@ import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.collect import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.RealBuffer +import space.kscience.kmath.structures.DoubleBuffer public interface Sampler { public fun sample(generator: RandomGenerator): Chain @@ -75,4 +75,4 @@ public fun Sampler.sampleBuffer( * Generate a bunch of samples from real distributions */ public fun Sampler.sampleBuffer(generator: RandomGenerator, size: Int): Chain> = - sampleBuffer(generator, size, ::RealBuffer) + sampleBuffer(generator, size, ::DoubleBuffer) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt index a9f7cd3e4..8bf6b09ef 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt @@ -81,7 +81,7 @@ public class Mean( public companion object { //TODO replace with optimized version which respects overflow - public val real: Mean = Mean(RealField) { sum, count -> sum / count } + public val real: Mean = Mean(DoubleField) { sum, count -> sum / count } public val int: Mean = Mean(IntRing) { sum, count -> sum / count } public val long: Mean = Mean(LongRing) { sum, count -> sum / count } } diff --git a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt index 1be436a4f..8b5551a16 100644 --- a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt +++ b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt @@ -2,8 +2,8 @@ package space.kscience.kmath.stat import org.apache.commons.rng.UniformRandomProvider import org.apache.commons.rng.sampling.distribution.* +import space.kscience.kmath.chains.BlockingDoubleChain import space.kscience.kmath.chains.BlockingIntChain -import space.kscience.kmath.chains.BlockingRealChain import space.kscience.kmath.chains.Chain import kotlin.math.PI import kotlin.math.exp @@ -11,7 +11,7 @@ import kotlin.math.pow import kotlin.math.sqrt public abstract class ContinuousSamplerDistribution : Distribution { - private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingRealChain() { + private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingDoubleChain() { private val sampler = buildCMSampler(generator) override fun nextDouble(): Double = sampler.sample() @@ -20,7 +20,7 @@ public abstract class ContinuousSamplerDistribution : Distribution { protected abstract fun buildCMSampler(generator: RandomGenerator): ContinuousSampler - public override fun sample(generator: RandomGenerator): BlockingRealChain = ContinuousSamplerChain(generator) + public override fun sample(generator: RandomGenerator): BlockingDoubleChain = ContinuousSamplerChain(generator) } public abstract class DiscreteSamplerDistribution : Distribution { diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api index d48a9f9c8..6fe6c9db7 100644 --- a/kmath-viktor/api/kmath-viktor.api +++ b/kmath-viktor/api/kmath-viktor.api @@ -67,7 +67,7 @@ public final class space/kscience/kmath/viktor/ViktorFieldND : space/kscience/km public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; public fun exp-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; - public fun getElementContext ()Lspace/kscience/kmath/operations/RealField; + public fun getElementContext ()Lspace/kscience/kmath/operations/DoubleField; public final fun getF64Buffer (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne-6kW2wQc ()Lorg/jetbrains/bio/viktor/F64Array; diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt index 9195415c5..2749f5431 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt @@ -3,9 +3,9 @@ package space.kscience.kmath.viktor import org.jetbrains.bio.viktor.F64Array import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.NumbersAddOperations -import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.ScaleOperations @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") @@ -26,7 +26,7 @@ public fun F64Array.asStructure(): ViktorStructureND = ViktorStructureND(this) @OptIn(UnstableKMathAPI::class) @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public class ViktorFieldND(public override val shape: IntArray) : FieldND, +public class ViktorFieldND(public override val shape: IntArray) : FieldND, NumbersAddOperations>, ExtendedField>, ScaleOperations> { @@ -46,39 +46,39 @@ public class ViktorFieldND(public override val shape: IntArray) : FieldND Double): ViktorStructureND = + public override fun produce(initializer: DoubleField.(IntArray) -> Double): ViktorStructureND = F64Array(*shape).apply { this@ViktorFieldND.strides.indices().forEach { index -> - set(value = RealField.initializer(index), indices = index) + set(value = DoubleField.initializer(index), indices = index) } }.asStructure() override fun StructureND.unaryMinus(): StructureND = -1 * this - public override fun StructureND.map(transform: RealField.(Double) -> Double): ViktorStructureND = + public override fun StructureND.map(transform: DoubleField.(Double) -> Double): ViktorStructureND = F64Array(*this@ViktorFieldND.shape).apply { this@ViktorFieldND.strides.indices().forEach { index -> - set(value = RealField.transform(this@map[index]), indices = index) + set(value = DoubleField.transform(this@map[index]), indices = index) } }.asStructure() public override fun StructureND.mapIndexed( - transform: RealField.(index: IntArray, Double) -> Double, + transform: DoubleField.(index: IntArray, Double) -> Double, ): ViktorStructureND = F64Array(*this@ViktorFieldND.shape).apply { this@ViktorFieldND.strides.indices().forEach { index -> - set(value = RealField.transform(index, this@mapIndexed[index]), indices = index) + set(value = DoubleField.transform(index, this@mapIndexed[index]), indices = index) } }.asStructure() public override fun combine( a: StructureND, b: StructureND, - transform: RealField.(Double, Double) -> Double, + transform: DoubleField.(Double, Double) -> Double, ): ViktorStructureND = F64Array(*shape).apply { this@ViktorFieldND.strides.indices().forEach { index -> - set(value = RealField.transform(a[index], b[index]), indices = index) + set(value = DoubleField.transform(a[index], b[index]), indices = index) } }.asStructure() From a3ca06a24142baec0a5cbe340ceea3da1cf103c6 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 16 Mar 2021 21:43:29 +0300 Subject: [PATCH 105/393] Remove StructureND identity #248 --- CHANGELOG.md | 1 + .../kmath/structures/StreamDoubleFieldND.kt | 54 +++---- .../structures/StructureReadBenchmark.kt | 4 +- .../kscience/kmath/commons/linear/CMMatrix.kt | 11 +- .../commons/transform/Transformations.kt | 2 + .../kscience/kmath/complex/ComplexFieldND.kt | 42 +++--- kmath-core/api/kmath-core.api | 132 ++++++++---------- .../kscience/kmath/linear/MatrixWrapper.kt | 2 - .../kscience/kmath/linear/VirtualMatrix.kt | 15 -- .../kscience/kmath/nd/BufferAlgebraND.kt | 20 +-- .../space/kscience/kmath/nd/DoubleFieldND.kt | 52 +++---- .../space/kscience/kmath/nd/ShortRingND.kt | 10 +- .../space/kscience/kmath/nd/Structure1D.kt | 4 +- .../space/kscience/kmath/nd/Structure2D.kt | 6 +- .../space/kscience/kmath/nd/StructureND.kt | 52 +++---- .../space/kscience/kmath/structures/Buffer.kt | 13 +- .../kmath/linear/DoubleLUSolverTest.kt | 12 +- .../space/kscience/kmath/linear/MatrixTest.kt | 3 +- .../kmath/structures/LazyStructureND.kt | 12 -- .../space/kscience/kmath/ejml/EjmlMatrix.kt | 13 +- .../kscience/kmath/ejml/EjmlMatrixTest.kt | 11 +- .../space/kscience/kmath/real/realND.kt | 20 +-- .../kaceince/kmath/real/DoubleMatrixTest.kt | 23 +-- .../kmath/histogram/DoubleHistogramSpace.kt | 2 +- .../kscience/kmath/nd4j/Nd4jArrayStructure.kt | 4 +- kmath-viktor/api/kmath-viktor.api | 2 +- .../kmath/viktor/ViktorStructureND.kt | 2 +- 27 files changed, 239 insertions(+), 285 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9e3f963e..644c634b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,6 +76,7 @@ - `toGrid` method. - Public visibility of `BufferAccessor2D` - `Real` class +- StructureND identity and equals ### Fixed - `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140) diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt index b4653b598..6741209fc 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -20,10 +20,10 @@ class StreamDoubleFieldND( private val strides = DefaultStrides(shape) override val elementContext: DoubleField get() = DoubleField - override val zero: NDBuffer by lazy { produce { zero } } - override val one: NDBuffer by lazy { produce { one } } + override val zero: BufferND by lazy { produce { zero } } + override val one: BufferND by lazy { produce { one } } - override fun number(value: Number): NDBuffer { + override fun number(value: Number): BufferND { val d = value.toDouble() // minimize conversions return produce { d } } @@ -34,30 +34,30 @@ class StreamDoubleFieldND( this@StreamDoubleFieldND.shape, shape ) - this is NDBuffer && this.strides == this@StreamDoubleFieldND.strides -> this.buffer as DoubleBuffer + this is BufferND && this.strides == this@StreamDoubleFieldND.strides -> this.buffer as DoubleBuffer else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } } - override fun produce(initializer: DoubleField.(IntArray) -> Double): NDBuffer { + override fun produce(initializer: DoubleField.(IntArray) -> Double): BufferND { val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset -> val index = strides.index(offset) DoubleField.initializer(index) }.toArray() - return NDBuffer(strides, array.asBuffer()) + return BufferND(strides, array.asBuffer()) } override fun StructureND.map( transform: DoubleField.(Double) -> Double, - ): NDBuffer { + ): BufferND { val array = Arrays.stream(buffer.array).parallel().map { DoubleField.transform(it) }.toArray() - return NDBuffer(strides, array.asBuffer()) + return BufferND(strides, array.asBuffer()) } override fun StructureND.mapIndexed( transform: DoubleField.(index: IntArray, Double) -> Double, - ): NDBuffer { + ): BufferND { val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset -> DoubleField.transform( strides.index(offset), @@ -65,43 +65,43 @@ class StreamDoubleFieldND( ) }.toArray() - return NDBuffer(strides, array.asBuffer()) + return BufferND(strides, array.asBuffer()) } override fun combine( a: StructureND, b: StructureND, transform: DoubleField.(Double, Double) -> Double, - ): NDBuffer { + ): BufferND { val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset -> DoubleField.transform(a.buffer.array[offset], b.buffer.array[offset]) }.toArray() - return NDBuffer(strides, array.asBuffer()) + return BufferND(strides, array.asBuffer()) } override fun StructureND.unaryMinus(): StructureND = map { -it } override fun scale(a: StructureND, value: Double): StructureND = a.map { it * value } - override fun power(arg: StructureND, pow: Number): NDBuffer = arg.map { power(it, pow) } + override fun power(arg: StructureND, pow: Number): BufferND = arg.map { power(it, pow) } - override fun exp(arg: StructureND): NDBuffer = arg.map { exp(it) } + override fun exp(arg: StructureND): BufferND = arg.map { exp(it) } - override fun ln(arg: StructureND): NDBuffer = arg.map { ln(it) } + override fun ln(arg: StructureND): BufferND = arg.map { ln(it) } - override fun sin(arg: StructureND): NDBuffer = arg.map { sin(it) } - override fun cos(arg: StructureND): NDBuffer = arg.map { cos(it) } - override fun tan(arg: StructureND): NDBuffer = arg.map { tan(it) } - override fun asin(arg: StructureND): NDBuffer = arg.map { asin(it) } - override fun acos(arg: StructureND): NDBuffer = arg.map { acos(it) } - override fun atan(arg: StructureND): NDBuffer = arg.map { atan(it) } + override fun sin(arg: StructureND): BufferND = arg.map { sin(it) } + override fun cos(arg: StructureND): BufferND = arg.map { cos(it) } + override fun tan(arg: StructureND): BufferND = arg.map { tan(it) } + override fun asin(arg: StructureND): BufferND = arg.map { asin(it) } + override fun acos(arg: StructureND): BufferND = arg.map { acos(it) } + override fun atan(arg: StructureND): BufferND = arg.map { atan(it) } - override fun sinh(arg: StructureND): NDBuffer = arg.map { sinh(it) } - override fun cosh(arg: StructureND): NDBuffer = arg.map { cosh(it) } - override fun tanh(arg: StructureND): NDBuffer = arg.map { tanh(it) } - override fun asinh(arg: StructureND): NDBuffer = arg.map { asinh(it) } - override fun acosh(arg: StructureND): NDBuffer = arg.map { acosh(it) } - override fun atanh(arg: StructureND): NDBuffer = arg.map { atanh(it) } + override fun sinh(arg: StructureND): BufferND = arg.map { sinh(it) } + override fun cosh(arg: StructureND): BufferND = arg.map { cosh(it) } + override fun tanh(arg: StructureND): BufferND = arg.map { tanh(it) } + override fun asinh(arg: StructureND): BufferND = arg.map { asinh(it) } + override fun acosh(arg: StructureND): BufferND = arg.map { acosh(it) } + override fun atanh(arg: StructureND): BufferND = arg.map { atanh(it) } } fun AlgebraND.Companion.realWithStream(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(shape) \ No newline at end of file diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt index 89f984a5b..1c8a923c7 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.structures +import space.kscience.kmath.nd.BufferND import space.kscience.kmath.nd.DefaultStrides -import space.kscience.kmath.nd.NDBuffer import kotlin.system.measureTimeMillis @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") @@ -10,7 +10,7 @@ fun main() { val array = DoubleArray(n * n) { 1.0 } val buffer = DoubleBuffer(array) val strides = DefaultStrides(intArrayOf(n, n)) - val structure = NDBuffer(strides, buffer) + val structure = BufferND(strides, buffer) measureTimeMillis { var res = 0.0 diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index 4efd8383b..89e9649e9 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -3,25 +3,16 @@ package space.kscience.kmath.commons.linear import org.apache.commons.math3.linear.* import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.DoubleBuffer import kotlin.reflect.KClass import kotlin.reflect.cast -public class CMMatrix(public val origin: RealMatrix) : Matrix { +public inline class CMMatrix(public val origin: RealMatrix) : Matrix { public override val rowNum: Int get() = origin.rowDimension public override val colNum: Int get() = origin.columnDimension public override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j) - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is StructureND<*>) return false - return StructureND.contentEquals(this, other) - } - - override fun hashCode(): Int = origin.hashCode() } public inline class CMVector(public val origin: RealVector) : Point { diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt index ad6b6d8cd..010ea7e9f 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt @@ -6,9 +6,11 @@ import kotlinx.coroutines.flow.map import org.apache.commons.math3.transform.* import space.kscience.kmath.complex.Complex import space.kscience.kmath.streaming.chunked +import space.kscience.kmath.streaming.spread import space.kscience.kmath.structures.* + /** * Streaming and buffer transformations */ diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt index e16962da7..d11f2b7db 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt @@ -2,8 +2,8 @@ package space.kscience.kmath.complex import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.AlgebraND +import space.kscience.kmath.nd.BufferND import space.kscience.kmath.nd.BufferedFieldND -import space.kscience.kmath.nd.NDBuffer import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.NumbersAddOperations @@ -22,10 +22,10 @@ public class ComplexFieldND( NumbersAddOperations>, ExtendedField> { - override val zero: NDBuffer by lazy { produce { zero } } - override val one: NDBuffer by lazy { produce { one } } + override val zero: BufferND by lazy { produce { zero } } + override val one: BufferND by lazy { produce { one } } - override fun number(value: Number): NDBuffer { + override fun number(value: Number): BufferND { val d = value.toComplex() // minimize conversions return produce { d } } @@ -76,35 +76,35 @@ public class ComplexFieldND( // return BufferedNDFieldElement(this, buffer) // } - override fun power(arg: StructureND, pow: Number): NDBuffer = arg.map { power(it, pow) } + override fun power(arg: StructureND, pow: Number): BufferND = arg.map { power(it, pow) } - override fun exp(arg: StructureND): NDBuffer = arg.map { exp(it) } + override fun exp(arg: StructureND): BufferND = arg.map { exp(it) } - override fun ln(arg: StructureND): NDBuffer = arg.map { ln(it) } + override fun ln(arg: StructureND): BufferND = arg.map { ln(it) } - override fun sin(arg: StructureND): NDBuffer = arg.map { sin(it) } - override fun cos(arg: StructureND): NDBuffer = arg.map { cos(it) } - override fun tan(arg: StructureND): NDBuffer = arg.map { tan(it) } - override fun asin(arg: StructureND): NDBuffer = arg.map { asin(it) } - override fun acos(arg: StructureND): NDBuffer = arg.map { acos(it) } - override fun atan(arg: StructureND): NDBuffer = arg.map { atan(it) } + override fun sin(arg: StructureND): BufferND = arg.map { sin(it) } + override fun cos(arg: StructureND): BufferND = arg.map { cos(it) } + override fun tan(arg: StructureND): BufferND = arg.map { tan(it) } + override fun asin(arg: StructureND): BufferND = arg.map { asin(it) } + override fun acos(arg: StructureND): BufferND = arg.map { acos(it) } + override fun atan(arg: StructureND): BufferND = arg.map { atan(it) } - override fun sinh(arg: StructureND): NDBuffer = arg.map { sinh(it) } - override fun cosh(arg: StructureND): NDBuffer = arg.map { cosh(it) } - override fun tanh(arg: StructureND): NDBuffer = arg.map { tanh(it) } - override fun asinh(arg: StructureND): NDBuffer = arg.map { asinh(it) } - override fun acosh(arg: StructureND): NDBuffer = arg.map { acosh(it) } - override fun atanh(arg: StructureND): NDBuffer = arg.map { atanh(it) } + override fun sinh(arg: StructureND): BufferND = arg.map { sinh(it) } + override fun cosh(arg: StructureND): BufferND = arg.map { cosh(it) } + override fun tanh(arg: StructureND): BufferND = arg.map { tanh(it) } + override fun asinh(arg: StructureND): BufferND = arg.map { asinh(it) } + override fun acosh(arg: StructureND): BufferND = arg.map { acosh(it) } + override fun atanh(arg: StructureND): BufferND = arg.map { atanh(it) } } /** * Fast element production using function inlining */ -public inline fun BufferedFieldND.produceInline(initializer: ComplexField.(Int) -> Complex): NDBuffer { +public inline fun BufferedFieldND.produceInline(initializer: ComplexField.(Int) -> Complex): BufferND { contract { callsInPlace(initializer, InvocationKind.EXACTLY_ONCE) } val buffer = Buffer.complex(strides.linearSize) { offset -> ComplexField.initializer(offset) } - return NDBuffer(strides, buffer) + return BufferND(strides, buffer) } diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 8be9ff115..5fabaae1b 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -584,7 +584,6 @@ public final class space/kscience/kmath/linear/MatrixFeaturesKt { public final class space/kscience/kmath/linear/MatrixWrapper : space/kscience/kmath/nd/Structure2D { public fun elements ()Lkotlin/sequences/Sequence; - public fun equals (Ljava/lang/Object;)Z public fun get (II)Ljava/lang/Object; public fun get ([I)Ljava/lang/Object; public fun getColNum ()I @@ -595,7 +594,6 @@ public final class space/kscience/kmath/linear/MatrixWrapper : space/kscience/km public fun getRowNum ()I public fun getRows ()Ljava/util/List; public fun getShape ()[I - public fun hashCode ()I public fun toString ()Ljava/lang/String; } @@ -640,7 +638,6 @@ public final class space/kscience/kmath/linear/UnitFeature : space/kscience/kmat public final class space/kscience/kmath/linear/VirtualMatrix : space/kscience/kmath/nd/Structure2D { public fun (IILkotlin/jvm/functions/Function2;)V public fun elements ()Lkotlin/sequences/Sequence; - public fun equals (Ljava/lang/Object;)Z public fun get (II)Ljava/lang/Object; public fun get ([I)Ljava/lang/Object; public fun getColNum ()I @@ -650,7 +647,6 @@ public final class space/kscience/kmath/linear/VirtualMatrix : space/kscience/km public fun getRowNum ()I public fun getRows ()Ljava/util/List; public fun getShape ()[I - public fun hashCode ()I } public final class space/kscience/kmath/linear/ZeroFeature : space/kscience/kmath/linear/DiagonalFeature { @@ -698,22 +694,22 @@ public final class space/kscience/kmath/nd/AlgebraND$DefaultImpls { } public abstract interface class space/kscience/kmath/nd/BufferAlgebraND : space/kscience/kmath/nd/AlgebraND { - public abstract fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public abstract fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; public abstract fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; public abstract fun getBufferFactory ()Lkotlin/jvm/functions/Function2; public abstract fun getStrides ()Lspace/kscience/kmath/nd/Strides; - public abstract fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; - public abstract fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; - public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public abstract fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; + public abstract fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; + public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; } public final class space/kscience/kmath/nd/BufferAlgebraND$DefaultImpls { - public static fun combine (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public static fun combine (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; public static fun getBuffer (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; public static fun invoke (Lspace/kscience/kmath/nd/BufferAlgebraND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun map (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; - public static fun mapIndexed (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; - public static fun produce (Lspace/kscience/kmath/nd/BufferAlgebraND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public static fun map (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; + public static fun mapIndexed (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; + public static fun produce (Lspace/kscience/kmath/nd/BufferAlgebraND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; } public final class space/kscience/kmath/nd/BufferAlgebraNDKt { @@ -725,6 +721,17 @@ public final class space/kscience/kmath/nd/BufferAlgebraNDKt { public static final fun ring (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedRingND; } +public class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/StructureND { + public fun (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/Buffer;)V + public fun elements ()Lkotlin/sequences/Sequence; + public fun get ([I)Ljava/lang/Object; + public fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; + public fun getDimension ()I + public fun getShape ()[I + public final fun getStrides ()Lspace/kscience/kmath/nd/Strides; + public fun toString ()Ljava/lang/String; +} + public class space/kscience/kmath/nd/BufferedFieldND : space/kscience/kmath/nd/BufferedRingND, space/kscience/kmath/nd/FieldND { public fun ([ILspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;)V public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; @@ -761,7 +768,7 @@ public class space/kscience/kmath/nd/BufferedGroupND : space/kscience/kmath/nd/B public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; - public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; public final fun getBufferFactory ()Lkotlin/jvm/functions/Function2; @@ -770,11 +777,11 @@ public class space/kscience/kmath/nd/BufferedGroupND : space/kscience/kmath/nd/B public final fun getShape ()[I public fun getStrides ()Lspace/kscience/kmath/nd/Strides; public synthetic fun getZero ()Ljava/lang/Object; - public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer; + public fun getZero ()Lspace/kscience/kmath/nd/BufferND; public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; - public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; @@ -784,7 +791,7 @@ public class space/kscience/kmath/nd/BufferedGroupND : space/kscience/kmath/nd/B public fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; public fun plus (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; @@ -799,7 +806,7 @@ public class space/kscience/kmath/nd/BufferedRingND : space/kscience/kmath/nd/Bu public fun ([ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun getOne ()Ljava/lang/Object; - public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer; + public fun getOne ()Lspace/kscience/kmath/nd/BufferND; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -828,43 +835,43 @@ public final class space/kscience/kmath/nd/DefaultStrides$Companion { public final class space/kscience/kmath/nd/DoubleFieldND : space/kscience/kmath/nd/BufferedFieldND, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { public fun ([I)V public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; - public fun acos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun acos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun acosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun acosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; - public fun asin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun asin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun asinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun asinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; - public fun atan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun atan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun atanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public fun atanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; + public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; - public fun cos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun cos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun cosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun cosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; - public fun exp (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun exp (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; public fun getBuffer-Udx-57Q (Lspace/kscience/kmath/nd/StructureND;)[D public synthetic fun getOne ()Ljava/lang/Object; - public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer; + public fun getOne ()Lspace/kscience/kmath/nd/BufferND; public synthetic fun getZero ()Ljava/lang/Object; - public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer; + public fun getZero ()Lspace/kscience/kmath/nd/BufferND; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; - public fun ln (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; - public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public fun ln (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; + public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; - public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/NDBuffer; + public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; @@ -873,22 +880,22 @@ public final class space/kscience/kmath/nd/DoubleFieldND : space/kscience/kmath/ public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun pow (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun power (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; - public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public fun power (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/BufferND; + public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; - public fun sin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun sin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun sinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun sinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; public fun sqrt (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; - public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun tanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/NDBuffer; + public fun tanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -965,32 +972,19 @@ public final class space/kscience/kmath/nd/GroupND$DefaultImpls { public static fun unaryPlus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } -public final class space/kscience/kmath/nd/MutableNDBuffer : space/kscience/kmath/nd/NDBuffer, space/kscience/kmath/nd/MutableNDStructure { +public final class space/kscience/kmath/nd/MutableBufferND : space/kscience/kmath/nd/BufferND, space/kscience/kmath/nd/MutableStructureND { public fun (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/MutableBuffer;)V public synthetic fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; public fun getBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; public fun set ([ILjava/lang/Object;)V } -public abstract interface class space/kscience/kmath/nd/MutableNDStructure : space/kscience/kmath/nd/StructureND { +public abstract interface class space/kscience/kmath/nd/MutableStructureND : space/kscience/kmath/nd/StructureND { public abstract fun set ([ILjava/lang/Object;)V } -public final class space/kscience/kmath/nd/MutableNDStructure$DefaultImpls { - public static fun getDimension (Lspace/kscience/kmath/nd/MutableNDStructure;)I -} - -public class space/kscience/kmath/nd/NDBuffer : space/kscience/kmath/nd/StructureND { - public fun (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/Buffer;)V - public fun elements ()Lkotlin/sequences/Sequence; - public fun equals (Ljava/lang/Object;)Z - public fun get ([I)Ljava/lang/Object; - public fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; - public fun getDimension ()I - public fun getShape ()[I - public final fun getStrides ()Lspace/kscience/kmath/nd/Strides; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; +public final class space/kscience/kmath/nd/MutableStructureND$DefaultImpls { + public static fun getDimension (Lspace/kscience/kmath/nd/MutableStructureND;)I } public abstract interface class space/kscience/kmath/nd/RingND : space/kscience/kmath/nd/GroupND, space/kscience/kmath/operations/Ring { @@ -1033,9 +1027,9 @@ public final class space/kscience/kmath/nd/ShapeMismatchException : java/lang/Ru public final class space/kscience/kmath/nd/ShortRingND : space/kscience/kmath/nd/BufferedRingND, space/kscience/kmath/operations/NumbersAddOperations { public fun ([I)V public synthetic fun getOne ()Ljava/lang/Object; - public fun getOne ()Lspace/kscience/kmath/nd/NDBuffer; + public fun getOne ()Lspace/kscience/kmath/nd/BufferND; public synthetic fun getZero ()Ljava/lang/Object; - public fun getZero ()Lspace/kscience/kmath/nd/NDBuffer; + public fun getZero ()Lspace/kscience/kmath/nd/BufferND; public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; @@ -1044,7 +1038,7 @@ public final class space/kscience/kmath/nd/ShortRingND : space/kscience/kmath/nd public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/NDBuffer; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; @@ -1056,7 +1050,7 @@ public final class space/kscience/kmath/nd/ShortRingND : space/kscience/kmath/nd public final class space/kscience/kmath/nd/ShortRingNDKt { public static final fun nd (Lspace/kscience/kmath/operations/ShortRing;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun produceInline (Lspace/kscience/kmath/nd/BufferedRingND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/NDBuffer; + public static final fun produceInline (Lspace/kscience/kmath/nd/BufferedRingND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; } public abstract interface class space/kscience/kmath/nd/Strides { @@ -1121,20 +1115,18 @@ public final class space/kscience/kmath/nd/Structure2DKt { public abstract interface class space/kscience/kmath/nd/StructureND { public static final field Companion Lspace/kscience/kmath/nd/StructureND$Companion; public abstract fun elements ()Lkotlin/sequences/Sequence; - public abstract fun equals (Ljava/lang/Object;)Z public abstract fun get ([I)Ljava/lang/Object; public abstract fun getDimension ()I public abstract fun getShape ()[I - public abstract fun hashCode ()I } public final class space/kscience/kmath/nd/StructureND$Companion { - public final fun auto (Lkotlin/reflect/KClass;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; - public final fun auto (Lkotlin/reflect/KClass;[ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; - public final fun buffered (Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; - public final fun buffered ([ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/NDBuffer; - public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer; - public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;[ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/NDBuffer; + public final fun auto (Lkotlin/reflect/KClass;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND; + public final fun auto (Lkotlin/reflect/KClass;[ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND; + public final fun buffered (Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND; + public final fun buffered ([ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND; + public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/BufferND; + public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;[ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/BufferND; public final fun contentEquals (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Z } @@ -1144,7 +1136,7 @@ public final class space/kscience/kmath/nd/StructureND$DefaultImpls { public final class space/kscience/kmath/nd/StructureNDKt { public static final fun get (Lspace/kscience/kmath/nd/StructureND;[I)Ljava/lang/Object; - public static final fun mapInPlace (Lspace/kscience/kmath/nd/MutableNDStructure;Lkotlin/jvm/functions/Function2;)V + public static final fun mapInPlace (Lspace/kscience/kmath/nd/MutableStructureND;Lkotlin/jvm/functions/Function2;)V } public abstract interface class space/kscience/kmath/operations/Algebra { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt index 97f0acd61..868f74cc6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt @@ -23,8 +23,6 @@ public class MatrixWrapper internal constructor( override fun getFeature(type: KClass): T? = features.singleOrNull { type.isInstance(it) } as? T ?: origin.getFeature(type) - override fun equals(other: Any?): Boolean = origin == other - override fun hashCode(): Int = origin.hashCode() override fun toString(): String { return "MatrixWrapper(matrix=$origin, features=$features)" } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt index 56cafbdb5..e80ee5ebd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt @@ -1,7 +1,5 @@ package space.kscience.kmath.linear -import space.kscience.kmath.nd.StructureND - /** * The matrix where each element is evaluated each time when is being accessed. * @@ -16,17 +14,4 @@ public class VirtualMatrix( override val shape: IntArray get() = intArrayOf(rowNum, colNum) override operator fun get(i: Int, j: Int): T = generator(i, j) - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is StructureND<*>) return false - return StructureND.contentEquals(this, other) - } - - override fun hashCode(): Int { - var result = rowNum - result = 31 * result + colNum - result = 31 * result + generator.hashCode() - return result - } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt index b81eb9519..67e94df74 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt @@ -10,7 +10,7 @@ public interface BufferAlgebraND> : AlgebraND { public val strides: Strides public val bufferFactory: BufferFactory - override fun produce(initializer: A.(IntArray) -> T): NDBuffer = NDBuffer( + override fun produce(initializer: A.(IntArray) -> T): BufferND = BufferND( strides, bufferFactory(strides.linearSize) { offset -> elementContext.initializer(strides.index(offset)) @@ -23,32 +23,32 @@ public interface BufferAlgebraND> : AlgebraND { this@BufferAlgebraND.shape, shape ) - this is NDBuffer && this.strides == this@BufferAlgebraND.strides -> this.buffer + this is BufferND && this.strides == this@BufferAlgebraND.strides -> this.buffer else -> bufferFactory(strides.linearSize) { offset -> get(strides.index(offset)) } } - override fun StructureND.map(transform: A.(T) -> T): NDBuffer { + override fun StructureND.map(transform: A.(T) -> T): BufferND { val buffer = bufferFactory(strides.linearSize) { offset -> elementContext.transform(buffer[offset]) } - return NDBuffer(strides, buffer) + return BufferND(strides, buffer) } - override fun StructureND.mapIndexed(transform: A.(index: IntArray, T) -> T): NDBuffer { + override fun StructureND.mapIndexed(transform: A.(index: IntArray, T) -> T): BufferND { val buffer = bufferFactory(strides.linearSize) { offset -> elementContext.transform( strides.index(offset), buffer[offset] ) } - return NDBuffer(strides, buffer) + return BufferND(strides, buffer) } - override fun combine(a: StructureND, b: StructureND, transform: A.(T, T) -> T): NDBuffer { + override fun combine(a: StructureND, b: StructureND, transform: A.(T, T) -> T): BufferND { val buffer = bufferFactory(strides.linearSize) { offset -> elementContext.transform(a.buffer[offset], b.buffer[offset]) } - return NDBuffer(strides, buffer) + return BufferND(strides, buffer) } } @@ -58,7 +58,7 @@ public open class BufferedGroupND>( final override val bufferFactory: BufferFactory, ) : GroupND, BufferAlgebraND { override val strides: Strides = DefaultStrides(shape) - override val zero: NDBuffer by lazy { produce { zero } } + override val zero: BufferND by lazy { produce { zero } } override fun StructureND.unaryMinus(): StructureND = produce { -get(it) } } @@ -67,7 +67,7 @@ public open class BufferedRingND>( elementContext: R, bufferFactory: BufferFactory, ) : BufferedGroupND(shape, elementContext, bufferFactory), RingND { - override val one: NDBuffer by lazy { produce { one } } + override val one: BufferND by lazy { produce { one } } } public open class BufferedFieldND>( diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt index a7a9d8935..d38ed02da 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt @@ -17,10 +17,10 @@ public class DoubleFieldND( ScaleOperations>, ExtendedField> { - override val zero: NDBuffer by lazy { produce { zero } } - override val one: NDBuffer by lazy { produce { one } } + override val zero: BufferND by lazy { produce { zero } } + override val one: BufferND by lazy { produce { one } } - override fun number(value: Number): NDBuffer { + override fun number(value: Number): BufferND { val d = value.toDouble() // minimize conversions return produce { d } } @@ -31,31 +31,31 @@ public class DoubleFieldND( this@DoubleFieldND.shape, shape ) - this is NDBuffer && this.strides == this@DoubleFieldND.strides -> this.buffer as DoubleBuffer + this is BufferND && this.strides == this@DoubleFieldND.strides -> this.buffer as DoubleBuffer else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } } @Suppress("OVERRIDE_BY_INLINE") override inline fun StructureND.map( transform: DoubleField.(Double) -> Double, - ): NDBuffer { + ): BufferND { val buffer = DoubleBuffer(strides.linearSize) { offset -> DoubleField.transform(buffer.array[offset]) } - return NDBuffer(strides, buffer) + return BufferND(strides, buffer) } @Suppress("OVERRIDE_BY_INLINE") - override inline fun produce(initializer: DoubleField.(IntArray) -> Double): NDBuffer { + override inline fun produce(initializer: DoubleField.(IntArray) -> Double): BufferND { val array = DoubleArray(strides.linearSize) { offset -> val index = strides.index(offset) DoubleField.initializer(index) } - return NDBuffer(strides, DoubleBuffer(array)) + return BufferND(strides, DoubleBuffer(array)) } @Suppress("OVERRIDE_BY_INLINE") override inline fun StructureND.mapIndexed( transform: DoubleField.(index: IntArray, Double) -> Double, - ): NDBuffer = NDBuffer( + ): BufferND = BufferND( strides, buffer = DoubleBuffer(strides.linearSize) { offset -> DoubleField.transform( @@ -69,34 +69,34 @@ public class DoubleFieldND( a: StructureND, b: StructureND, transform: DoubleField.(Double, Double) -> Double, - ): NDBuffer { + ): BufferND { val buffer = DoubleBuffer(strides.linearSize) { offset -> DoubleField.transform(a.buffer.array[offset], b.buffer.array[offset]) } - return NDBuffer(strides, buffer) + return BufferND(strides, buffer) } override fun scale(a: StructureND, value: Double): StructureND = a.map { it * value } - override fun power(arg: StructureND, pow: Number): NDBuffer = arg.map { power(it, pow) } + override fun power(arg: StructureND, pow: Number): BufferND = arg.map { power(it, pow) } - override fun exp(arg: StructureND): NDBuffer = arg.map { exp(it) } + override fun exp(arg: StructureND): BufferND = arg.map { exp(it) } - override fun ln(arg: StructureND): NDBuffer = arg.map { ln(it) } + override fun ln(arg: StructureND): BufferND = arg.map { ln(it) } - override fun sin(arg: StructureND): NDBuffer = arg.map { sin(it) } - override fun cos(arg: StructureND): NDBuffer = arg.map { cos(it) } - override fun tan(arg: StructureND): NDBuffer = arg.map { tan(it) } - override fun asin(arg: StructureND): NDBuffer = arg.map { asin(it) } - override fun acos(arg: StructureND): NDBuffer = arg.map { acos(it) } - override fun atan(arg: StructureND): NDBuffer = arg.map { atan(it) } + override fun sin(arg: StructureND): BufferND = arg.map { sin(it) } + override fun cos(arg: StructureND): BufferND = arg.map { cos(it) } + override fun tan(arg: StructureND): BufferND = arg.map { tan(it) } + override fun asin(arg: StructureND): BufferND = arg.map { asin(it) } + override fun acos(arg: StructureND): BufferND = arg.map { acos(it) } + override fun atan(arg: StructureND): BufferND = arg.map { atan(it) } - override fun sinh(arg: StructureND): NDBuffer = arg.map { sinh(it) } - override fun cosh(arg: StructureND): NDBuffer = arg.map { cosh(it) } - override fun tanh(arg: StructureND): NDBuffer = arg.map { tanh(it) } - override fun asinh(arg: StructureND): NDBuffer = arg.map { asinh(it) } - override fun acosh(arg: StructureND): NDBuffer = arg.map { acosh(it) } - override fun atanh(arg: StructureND): NDBuffer = arg.map { atanh(it) } + override fun sinh(arg: StructureND): BufferND = arg.map { sinh(it) } + override fun cosh(arg: StructureND): BufferND = arg.map { cosh(it) } + override fun tanh(arg: StructureND): BufferND = arg.map { tanh(it) } + override fun asinh(arg: StructureND): BufferND = arg.map { asinh(it) } + override fun acosh(arg: StructureND): BufferND = arg.map { acosh(it) } + override fun atanh(arg: StructureND): BufferND = arg.map { atanh(it) } } public fun AlgebraND.Companion.real(vararg shape: Int): DoubleFieldND = DoubleFieldND(shape) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt index 4e39dd544..f1056d0ff 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt @@ -14,10 +14,10 @@ public class ShortRingND( ) : BufferedRingND(shape, ShortRing, Buffer.Companion::auto), NumbersAddOperations> { - override val zero: NDBuffer by lazy { produce { zero } } - override val one: NDBuffer by lazy { produce { one } } + override val zero: BufferND by lazy { produce { zero } } + override val one: BufferND by lazy { produce { one } } - override fun number(value: Number): NDBuffer { + override fun number(value: Number): BufferND { val d = value.toShort() // minimize conversions return produce { d } } @@ -26,8 +26,8 @@ public class ShortRingND( /** * Fast element production using function inlining. */ -public inline fun BufferedRingND.produceInline(crossinline initializer: ShortRing.(Int) -> Short): NDBuffer { - return NDBuffer(strides, ShortBuffer(ShortArray(strides.linearSize) { offset -> ShortRing.initializer(offset) })) +public inline fun BufferedRingND.produceInline(crossinline initializer: ShortRing.(Int) -> Short): BufferND { + return BufferND(strides, ShortBuffer(ShortArray(strides.linearSize) { offset -> ShortRing.initializer(offset) })) } public inline fun ShortRing.nd(vararg shape: Int, action: ShortRingND.() -> R): R { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index eba51a980..8cf5d18cb 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -47,7 +47,7 @@ private inline class Buffer1DWrapper(val buffer: Buffer) : Structure1D */ public fun StructureND.as1D(): Structure1D = this as? Structure1D ?: if (shape.size == 1) { when (this) { - is NDBuffer -> Buffer1DWrapper(this.buffer) + is BufferND -> Buffer1DWrapper(this.buffer) else -> Structure1DWrapper(this) } } else error("Can't create 1d-structure from ${shape.size}d-structure") @@ -62,6 +62,6 @@ public fun Buffer.asND(): Structure1D = Buffer1DWrapper(this) */ internal fun Structure1D.unwrap(): Buffer = when { this is Buffer1DWrapper -> buffer - this is Structure1DWrapper && structure is NDBuffer -> structure.buffer + this is Structure1DWrapper && structure is BufferND -> structure.buffer else -> this } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 1c3b0fec8..3834cd97c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -60,7 +60,7 @@ public interface Structure2D : StructureND { /** * A 2D wrapper for nd-structure */ -private class Structure2DWrapper(val structure: StructureND) : Structure2D { +private inline class Structure2DWrapper(val structure: StructureND) : Structure2D { override val shape: IntArray get() = structure.shape override val rowNum: Int get() = shape[0] @@ -72,10 +72,6 @@ private class Structure2DWrapper(val structure: StructureND) : Structure2D override fun getFeature(type: KClass): F? = structure.getFeature(type) override fun elements(): Sequence> = structure.elements() - - override fun equals(other: Any?): Boolean = structure == other - - override fun hashCode(): Int = structure.hashCode() } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index 54253ba9e..bb7814bfd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -14,6 +14,8 @@ import kotlin.reflect.KClass * of dimensions and items in an array is defined by its shape, which is a sequence of non-negative integers that * specify the sizes of each dimension. * + * StructureND is in general identity-free. [StructureND.contentEquals] should be used in tests to compare contents. + * * @param T the type of items. */ public interface StructureND { @@ -43,10 +45,6 @@ public interface StructureND { */ public fun elements(): Sequence> - //force override equality and hash code - public override fun equals(other: Any?): Boolean - public override fun hashCode(): Int - /** * Feature is some additional strucure information which allows to access it special properties or hints. * If the feature is not present, null is returned. @@ -62,7 +60,7 @@ public interface StructureND { if (st1 === st2) return true // fast comparison of buffers if possible - if (st1 is NDBuffer && st2 is NDBuffer && st1.strides == st2.strides) + if (st1 is BufferND && st2 is BufferND && st1.strides == st2.strides) return st1.buffer.contentEquals(st2.buffer) //element by element comparison if it could not be avoided @@ -78,7 +76,7 @@ public interface StructureND { strides: Strides, bufferFactory: BufferFactory = Buffer.Companion::boxing, initializer: (IntArray) -> T, - ): NDBuffer = NDBuffer(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) }) + ): BufferND = BufferND(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) }) /** * Inline create NDStructure with non-boxing buffer implementation if it is possible @@ -86,37 +84,37 @@ public interface StructureND { public inline fun auto( strides: Strides, crossinline initializer: (IntArray) -> T, - ): NDBuffer = NDBuffer(strides, Buffer.auto(strides.linearSize) { i -> initializer(strides.index(i)) }) + ): BufferND = BufferND(strides, Buffer.auto(strides.linearSize) { i -> initializer(strides.index(i)) }) public inline fun auto( type: KClass, strides: Strides, crossinline initializer: (IntArray) -> T, - ): NDBuffer = NDBuffer(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) }) + ): BufferND = BufferND(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) }) public fun buffered( shape: IntArray, bufferFactory: BufferFactory = Buffer.Companion::boxing, initializer: (IntArray) -> T, - ): NDBuffer = buffered(DefaultStrides(shape), bufferFactory, initializer) + ): BufferND = buffered(DefaultStrides(shape), bufferFactory, initializer) public inline fun auto( shape: IntArray, crossinline initializer: (IntArray) -> T, - ): NDBuffer = auto(DefaultStrides(shape), initializer) + ): BufferND = auto(DefaultStrides(shape), initializer) @JvmName("autoVarArg") public inline fun auto( vararg shape: Int, crossinline initializer: (IntArray) -> T, - ): NDBuffer = + ): BufferND = auto(DefaultStrides(shape), initializer) public inline fun auto( type: KClass, vararg shape: Int, crossinline initializer: (IntArray) -> T, - ): NDBuffer = auto(type, DefaultStrides(shape), initializer) + ): BufferND = auto(type, DefaultStrides(shape), initializer) } } @@ -134,7 +132,7 @@ public inline fun StructureND<*>.getFeature(): T? = getFeature /** * Represents mutable [StructureND]. */ -public interface MutableNDStructure : StructureND { +public interface MutableStructureND : StructureND { /** * Inserts an item at the specified indices. * @@ -147,7 +145,7 @@ public interface MutableNDStructure : StructureND { /** * Transform a structure element-by element in place. */ -public inline fun MutableNDStructure.mapInPlace(action: (IntArray, T) -> T): Unit = +public inline fun MutableStructureND.mapInPlace(action: (IntArray, T) -> T): Unit = elements().forEach { (index, oldValue) -> this[index] = action(index, oldValue) } /** @@ -258,7 +256,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) : * @param strides The strides to access elements of [Buffer] by linear indices. * @param buffer The underlying buffer. */ -public open class NDBuffer( +public open class BufferND( public val strides: Strides, buffer: Buffer, ) : StructureND { @@ -279,16 +277,6 @@ public open class NDBuffer( it to this[it] } - override fun equals(other: Any?): Boolean { - return StructureND.contentEquals(this, other as? StructureND<*> ?: return false) - } - - override fun hashCode(): Int { - var result = strides.hashCode() - result = 31 * result + buffer.hashCode() - return result - } - override fun toString(): String { val bufferRepr: String = when (shape.size) { 1 -> buffer.asSequence().joinToString(prefix = "[", postfix = "]", separator = ", ") @@ -305,27 +293,27 @@ public open class NDBuffer( } /** - * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [NDBuffer] + * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferND] */ public inline fun StructureND.mapToBuffer( factory: BufferFactory = Buffer.Companion::auto, crossinline transform: (T) -> R, -): NDBuffer { - return if (this is NDBuffer) - NDBuffer(this.strides, factory.invoke(strides.linearSize) { transform(buffer[it]) }) +): BufferND { + return if (this is BufferND) + BufferND(this.strides, factory.invoke(strides.linearSize) { transform(buffer[it]) }) else { val strides = DefaultStrides(shape) - NDBuffer(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) + BufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) } } /** * Mutable ND buffer based on linear [MutableBuffer]. */ -public class MutableNDBuffer( +public class MutableBufferND( strides: Strides, buffer: MutableBuffer, -) : NDBuffer(strides, buffer), MutableNDStructure { +) : BufferND(strides, buffer), MutableStructureND { init { require(strides.linearSize == buffer.size) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 1c64bfcec..d373be35e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -17,7 +17,9 @@ public typealias BufferFactory = (Int, (Int) -> T) -> Buffer public typealias MutableBufferFactory = (Int, (Int) -> T) -> MutableBuffer /** - * A generic immutable random-access structure for both primitives and objects. + * A generic read-only random-access structure for both primitives and objects. + * + * [Buffer] is in general identity-free. [contentEquals] should be used for content equality checks * * @param T the type of elements contained in the buffer. */ @@ -40,8 +42,13 @@ public interface Buffer { /** * Checks content equality with another buffer. */ - public fun contentEquals(other: Buffer<*>): Boolean = - asSequence().mapIndexed { index, value -> value == other[index] }.all { it } + public fun contentEquals(other: Buffer<*>): Boolean { + if (this.size != other.size) return false + for (i in indices) { + if (get(i) != other[i]) return false + } + return true + } public companion object { /** diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt index 6761575f6..445aadd97 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt @@ -1,8 +1,14 @@ package space.kscience.kmath.linear import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.StructureND import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertTrue + +fun assertMatrixEquals(expected: StructureND, actual: StructureND) { + assertTrue { StructureND.contentEquals(expected, actual) } +} @UnstableKMathAPI class DoubleLUSolverTest { @@ -11,7 +17,7 @@ class DoubleLUSolverTest { fun testInvertOne() { val matrix = LinearSpace.real.one(2, 2) val inverted = LinearSpace.real.inverseWithLup(matrix) - assertEquals(matrix, inverted) + assertMatrixEquals(matrix, inverted) } @Test @@ -27,7 +33,7 @@ class DoubleLUSolverTest { //Check determinant assertEquals(7.0, lup.determinant) - assertEquals(lup.p dot matrix, lup.l dot lup.u) + assertMatrixEquals(lup.p dot matrix, lup.l dot lup.u) } } @@ -45,6 +51,6 @@ class DoubleLUSolverTest { -0.125, 0.375 ) - assertEquals(expected, inverted) + assertMatrixEquals(expected, inverted) } } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt index a8a2f2586..fd6fb320b 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt @@ -5,6 +5,7 @@ import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.as2D import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertTrue @UnstableKMathAPI @Suppress("UNUSED_VARIABLE") @@ -13,7 +14,7 @@ class MatrixTest { fun testTranspose() { val matrix = LinearSpace.real.one(3, 3) val transposed = matrix.transpose() - assertEquals(matrix, transposed) + assertTrue { StructureND.contentEquals(matrix, transposed) } } @Test diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt index 261f91aee..6b0938c54 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt @@ -24,18 +24,6 @@ public class LazyStructureND( val res = runBlocking { strides.indices().toList().map { index -> index to await(index) } } return res.asSequence() } - - public override fun equals(other: Any?): Boolean { - return StructureND.contentEquals(this, other as? StructureND<*> ?: return false) - } - - public override fun hashCode(): Int { - var result = scope.hashCode() - result = 31 * result + shape.contentHashCode() - result = 31 * result + function.hashCode() - result = 31 * result + cache.hashCode() - return result - } } public fun StructureND.deferred(index: IntArray): Deferred = diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index c79493411..712c2a42c 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -2,7 +2,6 @@ package space.kscience.kmath.ejml import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.Matrix -import space.kscience.kmath.nd.StructureND /** * Represents featured matrix over EJML [SimpleMatrix]. @@ -10,19 +9,9 @@ import space.kscience.kmath.nd.StructureND * @property origin the underlying [SimpleMatrix]. * @author Iaroslav Postovalov */ -public class EjmlMatrix(public val origin: SimpleMatrix) : Matrix { +public inline class EjmlMatrix(public val origin: SimpleMatrix) : Matrix { public override val rowNum: Int get() = origin.numRows() public override val colNum: Int get() = origin.numCols() public override operator fun get(i: Int, j: Int): Double = origin[i, j] - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is StructureND<*>) return false - return StructureND.contentEquals(this, other) - } - - override fun hashCode(): Int = origin.hashCode() - - } diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt index 70b2ce723..5fb526f40 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -4,11 +4,16 @@ import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.getFeature import kotlin.random.Random import kotlin.random.asJavaRandom import kotlin.test.* +fun assertMatrixEquals(expected: StructureND, actual: StructureND) { + assertTrue { StructureND.contentEquals(expected, actual) } +} + internal class EjmlMatrixTest { private val random = Random(0) @@ -49,9 +54,9 @@ internal class EjmlMatrixTest { val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows(), m.numCols()) .also { it.decompose(m.ddrm.copy()) } - assertEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getLower(null))), lup.l) - assertEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getUpper(null))), lup.u) - assertEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getRowPivot(null))), lup.p) + assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getLower(null))), lup.l) + assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getUpper(null))), lup.u) + assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getRowPivot(null))), lup.p) } private object SomeFeature : MatrixFeature {} diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt index 7655a4170..95faec4b3 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt @@ -1,31 +1,31 @@ package space.kscience.kmath.real -import space.kscience.kmath.nd.NDBuffer +import space.kscience.kmath.nd.BufferND import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.DoubleBuffer /** - * Map one [NDBuffer] using function without indices. + * Map one [BufferND] using function without indices. */ -public inline fun NDBuffer.mapInline(crossinline transform: DoubleField.(Double) -> Double): NDBuffer { +public inline fun BufferND.mapInline(crossinline transform: DoubleField.(Double) -> Double): BufferND { val array = DoubleArray(strides.linearSize) { offset -> DoubleField.transform(buffer[offset]) } - return NDBuffer(strides, DoubleBuffer(array)) + return BufferND(strides, DoubleBuffer(array)) } /** * Element by element application of any operation on elements to the whole array. Just like in numpy. */ -public operator fun Function1.invoke(ndElement: NDBuffer): NDBuffer = - ndElement.mapInline { this@invoke(it) } +public operator fun Function1.invoke(elementND: BufferND): BufferND = + elementND.mapInline { this@invoke(it) } /* plus and minus */ /** - * Summation operation for [NDBuffer] and single element + * Summation operation for [BufferND] and single element */ -public operator fun NDBuffer.plus(arg: Double): NDBuffer = mapInline { it + arg } +public operator fun BufferND.plus(arg: Double): BufferND = mapInline { it + arg } /** - * Subtraction operation between [NDBuffer] and single element + * Subtraction operation between [BufferND] and single element */ -public operator fun NDBuffer.minus(arg: Double): NDBuffer = mapInline { it - arg } \ No newline at end of file +public operator fun BufferND.minus(arg: Double): BufferND = mapInline { it - arg } \ No newline at end of file diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt index c1d3ccf5f..1c47d803a 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt @@ -3,12 +3,17 @@ package kaceince.kmath.real import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.matrix import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.StructureND import space.kscience.kmath.real.* import space.kscience.kmath.structures.contentEquals import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue +fun assertMatrixEquals(expected: StructureND, actual: StructureND) { + assertTrue { StructureND.contentEquals(expected, actual) } +} + @UnstableKMathAPI internal class DoubleMatrixTest { @Test @@ -43,7 +48,7 @@ internal class DoubleMatrixTest { 1.0, 0.0, 0.0, 0.0, 1.0, 2.0 ) - assertEquals(matrix2, matrix1.repeatStackVertical(3)) + assertMatrixEquals(matrix2, matrix1.repeatStackVertical(3)) } @Test @@ -57,7 +62,7 @@ internal class DoubleMatrixTest { 0.75, -0.5, 3.25, 4.5, 7.0, 2.0 ) - assertEquals(matrix2, expectedResult) + assertMatrixEquals(matrix2, expectedResult) } @Test @@ -72,7 +77,7 @@ internal class DoubleMatrixTest { 5.0, 10.0, -5.0, -10.0, -20.0, 0.0 ) - assertEquals(matrix2, expectedResult) + assertMatrixEquals(matrix2, expectedResult) } @Test @@ -89,8 +94,8 @@ internal class DoubleMatrixTest { -1.0, 0.0, 27.0, 64.0, -216.0, -8.0 ) - assertEquals(matrix1.square(), matrix2) - assertEquals(matrix1.pow(3), matrix3) + assertMatrixEquals(matrix1.square(), matrix2) + assertMatrixEquals(matrix1.pow(3), matrix3) } @OptIn(UnstableKMathAPI::class) @@ -109,7 +114,7 @@ internal class DoubleMatrixTest { -3.0, 0.0, 9.0, 16.0, -48.0, -5.0 ) - assertEquals(result, expectedResult) + assertMatrixEquals(result, expectedResult) } @Test @@ -128,9 +133,9 @@ internal class DoubleMatrixTest { -6.0, 7.0 ) - assertEquals(matrix1.appendColumn { it[0] }, matrix2) - assertEquals(matrix1.extractColumn(1), col1) - assertEquals(matrix1.extractColumns(1..2), cols1to2) + assertMatrixEquals(matrix1.appendColumn { it[0] }, matrix2) + assertMatrixEquals(matrix1.extractColumn(1), col1) + assertMatrixEquals(matrix1.extractColumns(1..2), cols1to2) //equals should never be called on buffers assertTrue { matrix1.sumByColumn().contentEquals(3.0, -6.0, 10.0, 4.0) diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/DoubleHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/DoubleHistogramSpace.kt index fa9b67404..384ce6159 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/DoubleHistogramSpace.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/DoubleHistogramSpace.kt @@ -75,7 +75,7 @@ public class DoubleHistogramSpace( ndCounter[index].add(value.toDouble()) } hBuilder.apply(builder) - val values: NDBuffer = ndCounter.mapToBuffer { it.value } + val values: BufferND = ndCounter.mapToBuffer { it.value } return IndexedHistogram(this, values) } diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt index ec4cc9c56..6a3ae37a7 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray -import space.kscience.kmath.nd.MutableNDStructure +import space.kscience.kmath.nd.MutableStructureND import space.kscience.kmath.nd.StructureND /** @@ -9,7 +9,7 @@ import space.kscience.kmath.nd.StructureND * * @param T the type of items. */ -public sealed class Nd4jArrayStructure : MutableNDStructure { +public sealed class Nd4jArrayStructure : MutableStructureND { /** * The wrapped [INDArray]. */ diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api index 6fe6c9db7..d322ddd71 100644 --- a/kmath-viktor/api/kmath-viktor.api +++ b/kmath-viktor/api/kmath-viktor.api @@ -148,7 +148,7 @@ public final class space/kscience/kmath/viktor/ViktorFieldND : space/kscience/km public fun unaryPlus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } -public final class space/kscience/kmath/viktor/ViktorStructureND : space/kscience/kmath/nd/MutableNDStructure { +public final class space/kscience/kmath/viktor/ViktorStructureND : space/kscience/kmath/nd/MutableStructureND { public static final synthetic fun box-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lspace/kscience/kmath/viktor/ViktorStructureND; public static fun constructor-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lorg/jetbrains/bio/viktor/F64Array; public fun elements ()Lkotlin/sequences/Sequence; diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt index 2749f5431..420bcac90 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.operations.NumbersAddOperations import space.kscience.kmath.operations.ScaleOperations @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public inline class ViktorStructureND(public val f64Buffer: F64Array) : MutableNDStructure { +public inline class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructureND { public override val shape: IntArray get() = f64Buffer.shape public override inline fun get(index: IntArray): Double = f64Buffer.get(*index) From 90981f6a401beb1e9ace8d6f4b6a27b9316ac825 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 16 Mar 2021 21:56:09 +0300 Subject: [PATCH 106/393] Remove contentEquals from Buffer --- kmath-core/api/kmath-core.api | 35 +------------------ .../space/kscience/kmath/nd/StructureND.kt | 4 +-- .../space/kscience/kmath/structures/Buffer.kt | 30 ++++++---------- .../kmath/expressions/SimpleAutoDiffTest.kt | 3 +- .../space/kscience/kmath/ejml/EjmlVector.kt | 6 ---- kmath-viktor/api/kmath-viktor.api | 2 -- 6 files changed, 15 insertions(+), 65 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 5fabaae1b..529f6c5f8 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -1073,7 +1073,6 @@ public abstract interface class space/kscience/kmath/nd/Structure1D : space/ksci } public final class space/kscience/kmath/nd/Structure1D$DefaultImpls { - public static fun contentEquals (Lspace/kscience/kmath/nd/Structure1D;Lspace/kscience/kmath/structures/Buffer;)Z public static fun get (Lspace/kscience/kmath/nd/Structure1D;[I)Ljava/lang/Object; public static fun getDimension (Lspace/kscience/kmath/nd/Structure1D;)I public static fun iterator (Lspace/kscience/kmath/nd/Structure1D;)Ljava/util/Iterator; @@ -2088,7 +2087,6 @@ public final class space/kscience/kmath/operations/TrigonometricOperations$Defau public final class space/kscience/kmath/structures/ArrayBuffer : space/kscience/kmath/structures/MutableBuffer { public fun ([Ljava/lang/Object;)V - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; public fun get (I)Ljava/lang/Object; public fun getSize ()I @@ -2098,7 +2096,6 @@ public final class space/kscience/kmath/structures/ArrayBuffer : space/kscience/ public abstract interface class space/kscience/kmath/structures/Buffer { public static final field Companion Lspace/kscience/kmath/structures/Buffer$Companion; - public abstract fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z public abstract fun get (I)Ljava/lang/Object; public abstract fun getSize ()I public abstract fun iterator ()Ljava/util/Iterator; @@ -2107,10 +2104,7 @@ public abstract interface class space/kscience/kmath/structures/Buffer { public final class space/kscience/kmath/structures/Buffer$Companion { public final fun auto (Lkotlin/reflect/KClass;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; public final fun boxing (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; -} - -public final class space/kscience/kmath/structures/Buffer$DefaultImpls { - public static fun contentEquals (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Z + public final fun contentEquals (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Z } public final class space/kscience/kmath/structures/BufferKt { @@ -2130,8 +2124,6 @@ public final class space/kscience/kmath/structures/BufferOperationKt { public final class space/kscience/kmath/structures/DoubleBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl ([D)Lspace/kscience/kmath/structures/DoubleBuffer; public static fun constructor-impl ([D)[D - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z - public static fun contentEquals-impl ([DLspace/kscience/kmath/structures/Buffer;)Z public synthetic fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; public fun copy-Dv3HvWU ()[D public static fun copy-Dv3HvWU ([D)[D @@ -2318,10 +2310,6 @@ public abstract interface class space/kscience/kmath/structures/FlaggedBuffer : public abstract fun getFlag (I)B } -public final class space/kscience/kmath/structures/FlaggedBuffer$DefaultImpls { - public static fun contentEquals (Lspace/kscience/kmath/structures/FlaggedBuffer;Lspace/kscience/kmath/structures/Buffer;)Z -} - public final class space/kscience/kmath/structures/FlaggedBufferKt { public static final fun forEachValid (Lspace/kscience/kmath/structures/FlaggedDoubleBuffer;Lkotlin/jvm/functions/Function1;)V public static final fun hasFlag (Lspace/kscience/kmath/structures/FlaggedBuffer;ILspace/kscience/kmath/structures/ValueFlag;)Z @@ -2331,7 +2319,6 @@ public final class space/kscience/kmath/structures/FlaggedBufferKt { public final class space/kscience/kmath/structures/FlaggedDoubleBuffer : space/kscience/kmath/structures/Buffer, space/kscience/kmath/structures/FlaggedBuffer { public fun ([D[B)V - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z public fun get (I)Ljava/lang/Double; public synthetic fun get (I)Ljava/lang/Object; public fun getFlag (I)B @@ -2344,8 +2331,6 @@ public final class space/kscience/kmath/structures/FlaggedDoubleBuffer : space/k public final class space/kscience/kmath/structures/FloatBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl ([F)Lspace/kscience/kmath/structures/FloatBuffer; public static fun constructor-impl ([F)[F - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z - public static fun contentEquals-impl ([FLspace/kscience/kmath/structures/Buffer;)Z public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; public static fun copy-impl ([F)Lspace/kscience/kmath/structures/MutableBuffer; public fun equals (Ljava/lang/Object;)Z @@ -2380,8 +2365,6 @@ public final class space/kscience/kmath/structures/FloatBufferKt { public final class space/kscience/kmath/structures/IntBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl ([I)Lspace/kscience/kmath/structures/IntBuffer; public static fun constructor-impl ([I)[I - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z - public static fun contentEquals-impl ([ILspace/kscience/kmath/structures/Buffer;)Z public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; public static fun copy-impl ([I)Lspace/kscience/kmath/structures/MutableBuffer; public fun equals (Ljava/lang/Object;)Z @@ -2416,8 +2399,6 @@ public final class space/kscience/kmath/structures/IntBufferKt { public final class space/kscience/kmath/structures/ListBuffer : space/kscience/kmath/structures/Buffer { public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/ListBuffer; public static fun constructor-impl (Ljava/util/List;)Ljava/util/List; - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z - public static fun contentEquals-impl (Ljava/util/List;Lspace/kscience/kmath/structures/Buffer;)Z public fun equals (Ljava/lang/Object;)Z public static fun equals-impl (Ljava/util/List;Ljava/lang/Object;)Z public static final fun equals-impl0 (Ljava/util/List;Ljava/util/List;)Z @@ -2438,8 +2419,6 @@ public final class space/kscience/kmath/structures/ListBuffer : space/kscience/k public final class space/kscience/kmath/structures/LongBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl ([J)Lspace/kscience/kmath/structures/LongBuffer; public static fun constructor-impl ([J)[J - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z - public static fun contentEquals-impl ([JLspace/kscience/kmath/structures/Buffer;)Z public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; public static fun copy-impl ([J)Lspace/kscience/kmath/structures/MutableBuffer; public fun equals (Ljava/lang/Object;)Z @@ -2474,7 +2453,6 @@ public final class space/kscience/kmath/structures/LongBufferKt { public class space/kscience/kmath/structures/MemoryBuffer : space/kscience/kmath/structures/Buffer { public static final field Companion Lspace/kscience/kmath/structures/MemoryBuffer$Companion; public fun (Lspace/kscience/kmath/memory/Memory;Lspace/kscience/kmath/memory/MemorySpec;)V - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z public fun get (I)Ljava/lang/Object; protected final fun getMemory ()Lspace/kscience/kmath/memory/Memory; public fun getSize ()I @@ -2503,15 +2481,9 @@ public final class space/kscience/kmath/structures/MutableBuffer$Companion { public final fun short-1yRgbGw (ILkotlin/jvm/functions/Function1;)[S } -public final class space/kscience/kmath/structures/MutableBuffer$DefaultImpls { - public static fun contentEquals (Lspace/kscience/kmath/structures/MutableBuffer;Lspace/kscience/kmath/structures/Buffer;)Z -} - public final class space/kscience/kmath/structures/MutableListBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/MutableListBuffer; public static fun constructor-impl (Ljava/util/List;)Ljava/util/List; - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z - public static fun contentEquals-impl (Ljava/util/List;Lspace/kscience/kmath/structures/Buffer;)Z public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; public static fun copy-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/MutableBuffer; public fun equals (Ljava/lang/Object;)Z @@ -2548,8 +2520,6 @@ public final class space/kscience/kmath/structures/MutableMemoryBuffer$Companion public final class space/kscience/kmath/structures/ReadOnlyBuffer : space/kscience/kmath/structures/Buffer { public static final synthetic fun box-impl (Lspace/kscience/kmath/structures/MutableBuffer;)Lspace/kscience/kmath/structures/ReadOnlyBuffer; public static fun constructor-impl (Lspace/kscience/kmath/structures/MutableBuffer;)Lspace/kscience/kmath/structures/MutableBuffer; - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z - public static fun contentEquals-impl (Lspace/kscience/kmath/structures/MutableBuffer;Lspace/kscience/kmath/structures/Buffer;)Z public fun equals (Ljava/lang/Object;)Z public static fun equals-impl (Lspace/kscience/kmath/structures/MutableBuffer;Ljava/lang/Object;)Z public static final fun equals-impl0 (Lspace/kscience/kmath/structures/MutableBuffer;Lspace/kscience/kmath/structures/MutableBuffer;)Z @@ -2570,8 +2540,6 @@ public final class space/kscience/kmath/structures/ReadOnlyBuffer : space/kscien public final class space/kscience/kmath/structures/ShortBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl ([S)Lspace/kscience/kmath/structures/ShortBuffer; public static fun constructor-impl ([S)[S - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z - public static fun contentEquals-impl ([SLspace/kscience/kmath/structures/Buffer;)Z public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; public static fun copy-impl ([S)Lspace/kscience/kmath/structures/MutableBuffer; public fun equals (Ljava/lang/Object;)Z @@ -2615,7 +2583,6 @@ public final class space/kscience/kmath/structures/ValueFlag : java/lang/Enum { public final class space/kscience/kmath/structures/VirtualBuffer : space/kscience/kmath/structures/Buffer { public fun (ILkotlin/jvm/functions/Function1;)V - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z public fun get (I)Ljava/lang/Object; public fun getSize ()I public fun iterator ()Ljava/util/Iterator; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index bb7814bfd..b31ce3eac 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -56,12 +56,12 @@ public interface StructureND { /** * Indicates whether some [StructureND] is equal to another one. */ - public fun contentEquals(st1: StructureND<*>, st2: StructureND<*>): Boolean { + public fun contentEquals(st1: StructureND, st2: StructureND): Boolean { if (st1 === st2) return true // fast comparison of buffers if possible if (st1 is BufferND && st2 is BufferND && st1.strides == st2.strides) - return st1.buffer.contentEquals(st2.buffer) + return Buffer.contentEquals(st1.buffer, st2.buffer) //element by element comparison if it could not be avoided return st1.elements().all { (index, value) -> value == st2[index] } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index d373be35e..b29181cea 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -19,7 +19,7 @@ public typealias MutableBufferFactory = (Int, (Int) -> T) -> MutableBuffer /** * A generic read-only random-access structure for both primitives and objects. * - * [Buffer] is in general identity-free. [contentEquals] should be used for content equality checks + * [Buffer] is in general identity-free. [Buffer.contentEquals] should be used for content equality checks. * * @param T the type of elements contained in the buffer. */ @@ -39,18 +39,16 @@ public interface Buffer { */ public operator fun iterator(): Iterator - /** - * Checks content equality with another buffer. - */ - public fun contentEquals(other: Buffer<*>): Boolean { - if (this.size != other.size) return false - for (i in indices) { - if (get(i) != other[i]) return false - } - return true - } - public companion object { + + public fun contentEquals(first: Buffer, second: Buffer): Boolean{ + if (first.size != second.size) return false + for (i in first.indices) { + if (first[i] != second[i]) return false + } + return true + } + /** * Creates a [ListBuffer] of given type [T] with given [size]. Each element is calculated by calling the * specified [initializer] function. @@ -279,14 +277,6 @@ public class VirtualBuffer(override val size: Int, private val generator: (In } override operator fun iterator(): Iterator = (0 until size).asSequence().map(generator).iterator() - - override fun contentEquals(other: Buffer<*>): Boolean { - return if (other is VirtualBuffer) { - this.size == other.size && this.generator == other.generator - } else { - super.contentEquals(other) - } - } } /** diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt index 95b2b2d1c..ca7aca905 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.expressions import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer import kotlin.math.E import kotlin.math.PI @@ -276,7 +277,7 @@ class SimpleAutoDiffTest { fun testDivGrad() { val res = dxy(x to 1.0, y to 2.0) { x, y -> x * x + y * y } assertEquals(6.0, res.div()) - assertTrue(res.grad(x, y).contentEquals(doubleArrayOf(2.0, 4.0).asBuffer())) + assertTrue(Buffer.contentEquals(res.grad(x, y), doubleArrayOf(2.0, 4.0).asBuffer())) } private fun assertApprox(a: Double, b: Double) { diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt index efa1f6128..c7f87675d 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt @@ -2,7 +2,6 @@ package space.kscience.kmath.ejml import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.Point -import space.kscience.kmath.structures.Buffer /** * Represents point over EJML [SimpleMatrix]. @@ -31,10 +30,5 @@ public class EjmlVector internal constructor(public val origin: SimpleMatrix) : override fun hasNext(): Boolean = cursor < origin.numCols() * origin.numRows() } - public override fun contentEquals(other: Buffer<*>): Boolean { - if (other is EjmlVector) return origin.isIdentical(other.origin, 0.0) - return super.contentEquals(other) - } - public override fun toString(): String = "EjmlVector(origin=$origin)" } diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api index d322ddd71..0b9ea1b48 100644 --- a/kmath-viktor/api/kmath-viktor.api +++ b/kmath-viktor/api/kmath-viktor.api @@ -1,8 +1,6 @@ public final class space/kscience/kmath/viktor/ViktorBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)Lspace/kscience/kmath/viktor/ViktorBuffer; public static fun constructor-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)Lorg/jetbrains/bio/viktor/F64FlatArray; - public fun contentEquals (Lspace/kscience/kmath/structures/Buffer;)Z - public static fun contentEquals-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;Lspace/kscience/kmath/structures/Buffer;)Z public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; public static fun copy-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)Lspace/kscience/kmath/structures/MutableBuffer; public fun equals (Ljava/lang/Object;)Z From 248d42c4e0656d478efa890ddd55c799ed3cef8e Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 16 Mar 2021 22:46:22 +0300 Subject: [PATCH 107/393] Remove MutableBufferND --- CHANGELOG.md | 1 + README.md | 54 +++++----- build.gradle.kts | 2 +- kmath-ast/README.md | 24 ++--- kmath-ast/build.gradle.kts | 12 +-- kmath-complex/README.md | 16 +-- kmath-complex/build.gradle.kts | 4 +- kmath-core/README.md | 26 ++--- kmath-core/api/kmath-core.api | 12 +-- kmath-core/build.gradle.kts | 14 +-- .../space/kscience/kmath/nd/BufferND.kt | 48 +++++++++ .../space/kscience/kmath/nd/StructureND.kt | 100 ++++-------------- .../space/kscience/kmath/structures/Buffer.kt | 3 + kmath-for-real/README.md | 18 ++-- kmath-for-real/build.gradle.kts | 6 +- kmath-functions/README.md | 20 ++-- kmath-functions/build.gradle.kts | 8 +- kmath-nd4j/README.md | 24 ++--- kmath-nd4j/build.gradle.kts | 9 +- 19 files changed, 174 insertions(+), 227 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 644c634b2..8b4dddf81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ ### Removed - Nearest in Domain. To be implemented in geometry package. - Number multiplication and division in main Algebra chain +- `contentEquals` from Buffer. It moved to the companion. ### Fixed diff --git a/README.md b/README.md index 436495c9c..2aaeb3150 100644 --- a/README.md +++ b/README.md @@ -87,12 +87,12 @@ KMath is a modular library. Different modules provide different features with di > **Maturity**: PROTOTYPE > > **Features:** -> - [expression-language](kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt) : Expression language and its parser -> - [mst](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation -> - [mst-building](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure -> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST interpreter -> - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler -> - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler +> - [expression-language](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser +> - [mst](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation +> - [mst-building](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure +> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter +> - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler +> - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
@@ -108,8 +108,8 @@ KMath is a modular library. Different modules provide different features with di > **Maturity**: PROTOTYPE > > **Features:** -> - [complex](kmath-complex/src/commonMain/kotlin/kscience/kmath/complex/Complex.kt) : Complex Numbers -> - [quaternion](kmath-complex/src/commonMain/kotlin/kscience/kmath/complex/Quaternion.kt) : Quaternions +> - [complex](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers +> - [quaternion](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions
@@ -119,15 +119,15 @@ KMath is a modular library. Different modules provide different features with di > **Maturity**: DEVELOPMENT > > **Features:** -> - [algebras](kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields. -> - [nd](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures and operations on them. -> - [linear](kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition. -> - [buffers](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure -> - [expressions](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of +> - [algebras](kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields. +> - [nd](kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt) : Many-dimensional structures and operations on them. +> - [linear](kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition. +> - [buffers](kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt) : One-dimensional structure +> - [expressions](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high performance calculations to code generation. -> - [domains](kmath-core/src/commonMain/kotlin/kscience/kmath/domains) : Domains -> - [autodif](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation +> - [domains](kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains) : Domains +> - [autodif](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
@@ -157,9 +157,9 @@ One can still use generic algebras though. > **Maturity**: EXPERIMENTAL > > **Features:** -> - [RealVector](kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt) : Numpy-like operations for Buffers/Points -> - [RealMatrix](kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt) : Numpy-like operations for 2d real structures -> - [grids](kmath-for-real/src/commonMain/kotlin/kscience/kmath/structures/grids.kt) : Uniform grid generators +> - [DoubleVector](kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt) : Numpy-like operations for Buffers/Points +> - [DoubleMatrix](kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt) : Numpy-like operations for 2d real structures +> - [grids](kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt) : Uniform grid generators
@@ -169,10 +169,10 @@ One can still use generic algebras though. > **Maturity**: PROTOTYPE > > **Features:** -> - [piecewise](kmath-functions/Piecewise functions.) : src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt -> - [polynomials](kmath-functions/Polynomial functions.) : src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt -> - [linear interpolation](kmath-functions/Linear XY interpolator.) : src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt -> - [spline interpolation](kmath-functions/Cubic spline XY interpolator.) : src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt +> - [piecewise](kmath-functions/Piecewise functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +> - [polynomials](kmath-functions/Polynomial functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +> - [linear interpolation](kmath-functions/Linear XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +> - [spline interpolation](kmath-functions/Cubic spline XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt
@@ -206,9 +206,9 @@ One can still use generic algebras though. > **Maturity**: EXPERIMENTAL > > **Features:** -> - [nd4jarraystructure](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray -> - [nd4jarrayrings](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long -> - [nd4jarrayfields](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double +> - [nd4jarraystructure](kmath-nd4j/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray +> - [nd4jarrayrings](kmath-nd4j/src/commonMain/kotlin/space/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long +> - [nd4jarrayfields](kmath-nd4j/src/commonMain/kotlin/space/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double
@@ -254,8 +254,8 @@ repositories { } dependencies { - api("space.kscience:kmath-core:0.3.0-dev-2") - // api("kscience.kmath:kmath-core-jvm:0.3.0-dev-2") for jvm-specific version + api("space.kscience:kmath-core:0.3.0-dev-3") + // api("kscience.kmath:kmath-core-jvm:0.3.0-dev-3") for jvm-specific version } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 9810e378f..5f1a8b88a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,7 +20,7 @@ allprojects { } group = "space.kscience" - version = "0.3.0-dev-2" + version = "0.3.0-dev-3" } subprojects { diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 1b3f70080..4c79b5b36 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -2,17 +2,17 @@ This subproject implements the following features: - - [expression-language](src/jvmMain/kotlin/kscience/kmath/ast/parser.kt) : Expression language and its parser - - [mst](src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation - - [mst-building](src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure - - [mst-interpreter](src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST interpreter - - [mst-jvm-codegen](src/jvmMain/kotlin/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler - - [mst-js-codegen](src/jsMain/kotlin/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler + - [expression-language](src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser + - [mst](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation + - [mst-building](src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure + - [mst-interpreter](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter + - [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler + - [mst-js-codegen](src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler > #### Artifact: > -> This module artifact: `space.kscience:kmath-ast:0.3.0-dev-2`. +> This module artifact: `space.kscience:kmath-ast:0.3.0-dev-3`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-ast/_latestVersion) > @@ -25,13 +25,10 @@ This subproject implements the following features: > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { -> implementation 'space.kscience:kmath-ast:0.3.0-dev-2' +> implementation 'space.kscience:kmath-ast:0.3.0-dev-3' > } > ``` > **Gradle Kotlin DSL:** @@ -41,13 +38,10 @@ This subproject implements the following features: > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { -> implementation("space.kscience:kmath-ast:0.3.0-dev-2") +> implementation("space.kscience:kmath-ast:0.3.0-dev-3") > } > ``` diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 5b764459c..e3a7faf0a 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -58,36 +58,36 @@ readme { feature( id = "expression-language", description = "Expression language and its parser", - ref = "src/jvmMain/kotlin/kscience/kmath/ast/parser.kt" + ref = "src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt" ) feature( id = "mst", description = "MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation", - ref = "src/commonMain/kotlin/kscience/kmath/ast/MST.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt" ) feature( id = "mst-building", description = "MST building algebraic structure", - ref = "src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt" ) feature( id = "mst-interpreter", description = "MST interpreter", - ref = "src/commonMain/kotlin/kscience/kmath/ast/MST.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt" ) feature( id = "mst-jvm-codegen", description = "Dynamic MST to JVM bytecode compiler", - ref = "src/jvmMain/kotlin/kscience/kmath/asm/asm.kt" + ref = "src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt" ) feature( id = "mst-js-codegen", description = "Dynamic MST to JS compiler", - ref = "src/jsMain/kotlin/kscience/kmath/estree/estree.kt" + ref = "src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt" ) } diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 7a7628a2c..9e9cd5b6f 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -2,13 +2,13 @@ Complex and hypercomplex number systems in KMath: - - [complex](src/commonMain/kotlin/kscience/kmath/complex/Complex.kt) : Complex Numbers - - [quaternion](src/commonMain/kotlin/kscience/kmath/complex/Quaternion.kt) : Quaternions + - [complex](src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers + - [quaternion](src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions > #### Artifact: > -> This module artifact: `space.kscience:kmath-complex:0.3.0-dev-2`. +> This module artifact: `space.kscience:kmath-complex:0.3.0-dev-3`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-complex/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-complex/_latestVersion) > @@ -21,13 +21,10 @@ Complex and hypercomplex number systems in KMath: > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { -> implementation 'space.kscience:kmath-complex:0.3.0-dev-2' +> implementation 'space.kscience:kmath-complex:0.3.0-dev-3' > } > ``` > **Gradle Kotlin DSL:** @@ -37,12 +34,9 @@ Complex and hypercomplex number systems in KMath: > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { -> implementation("space.kscience:kmath-complex:0.3.0-dev-2") +> implementation("space.kscience:kmath-complex:0.3.0-dev-3") > } > ``` diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index 4cd43c70c..5b9dc3ba0 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -25,12 +25,12 @@ readme { feature( id = "complex", description = "Complex Numbers", - ref = "src/commonMain/kotlin/kscience/kmath/complex/Complex.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt" ) feature( id = "quaternion", description = "Quaternions", - ref = "src/commonMain/kotlin/kscience/kmath/complex/Quaternion.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt" ) } diff --git a/kmath-core/README.md b/kmath-core/README.md index 14f1ecb41..dd54b7aeb 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -2,20 +2,20 @@ The core features of KMath: - - [algebras](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields. - - [nd](src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures and operations on them. - - [linear](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition. - - [buffers](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure - - [expressions](src/commonMain/kotlin/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of + - [algebras](src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields. + - [nd](src/commonMain/kotlin/space/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures and operations on them. + - [linear](src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition. + - [buffers](src/commonMain/kotlin/space/kscience/kmath/structures/Buffers.kt) : One-dimensional structure + - [expressions](src/commonMain/kotlin/space/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high performance calculations to code generation. - - [domains](src/commonMain/kotlin/kscience/kmath/domains) : Domains - - [autodif](src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation + - [domains](src/commonMain/kotlin/space/kscience/kmath/domains) : Domains + - [autodif](src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation > #### Artifact: > -> This module artifact: `space.kscience:kmath-core:0.3.0-dev-2`. +> This module artifact: `space.kscience:kmath-core:0.3.0-dev-3`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) > @@ -28,13 +28,10 @@ performance calculations to code generation. > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { -> implementation 'space.kscience:kmath-core:0.3.0-dev-2' +> implementation 'space.kscience:kmath-core:0.3.0-dev-3' > } > ``` > **Gradle Kotlin DSL:** @@ -44,12 +41,9 @@ performance calculations to code generation. > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { -> implementation("space.kscience:kmath-core:0.3.0-dev-2") +> implementation("space.kscience:kmath-core:0.3.0-dev-3") > } > ``` diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 529f6c5f8..04325379e 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -721,11 +721,11 @@ public final class space/kscience/kmath/nd/BufferAlgebraNDKt { public static final fun ring (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedRingND; } -public class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/StructureND { +public final class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/StructureND { public fun (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/Buffer;)V public fun elements ()Lkotlin/sequences/Sequence; public fun get ([I)Ljava/lang/Object; - public fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; + public final fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; public fun getDimension ()I public fun getShape ()[I public final fun getStrides ()Lspace/kscience/kmath/nd/Strides; @@ -972,13 +972,6 @@ public final class space/kscience/kmath/nd/GroupND$DefaultImpls { public static fun unaryPlus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } -public final class space/kscience/kmath/nd/MutableBufferND : space/kscience/kmath/nd/BufferND, space/kscience/kmath/nd/MutableStructureND { - public fun (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/MutableBuffer;)V - public synthetic fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; - public fun getBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; - public fun set ([ILjava/lang/Object;)V -} - public abstract interface class space/kscience/kmath/nd/MutableStructureND : space/kscience/kmath/nd/StructureND { public abstract fun set ([ILjava/lang/Object;)V } @@ -1127,6 +1120,7 @@ public final class space/kscience/kmath/nd/StructureND$Companion { public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/BufferND; public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;[ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/BufferND; public final fun contentEquals (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Z + public final fun toString (Lspace/kscience/kmath/nd/StructureND;)Ljava/lang/String; } public final class space/kscience/kmath/nd/StructureND$DefaultImpls { diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 8d30f1d6e..2fed3eb2f 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -23,13 +23,13 @@ readme { description = """ Algebraic structures like rings, spaces and fields. """.trimIndent(), - ref = "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt" ) feature( id = "nd", description = "Many-dimensional structures and operations on them.", - ref = "src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt" ) feature( @@ -37,13 +37,13 @@ readme { description = """ Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition. """.trimIndent(), - ref = "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt" ) feature( id = "buffers", description = "One-dimensional structure", - ref = "src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/structures/Buffers.kt" ) feature( @@ -53,18 +53,18 @@ readme { objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high performance calculations to code generation. """.trimIndent(), - ref = "src/commonMain/kotlin/kscience/kmath/expressions" + ref = "src/commonMain/kotlin/space/kscience/kmath/expressions" ) feature( id = "domains", description = "Domains", - ref = "src/commonMain/kotlin/kscience/kmath/domains" + ref = "src/commonMain/kotlin/space/kscience/kmath/domains" ) feature( id = "autodif", description = "Automatic differentiation", - ref = "src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt" ) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt new file mode 100644 index 000000000..c7f8d222d --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt @@ -0,0 +1,48 @@ +package space.kscience.kmath.nd + +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferFactory + +/** + * Represents [StructureND] over [Buffer]. + * + * @param T the type of items. + * @param strides The strides to access elements of [Buffer] by linear indices. + * @param buffer The underlying buffer. + */ +public class BufferND( + public val strides: Strides, + public val buffer: Buffer, +) : StructureND { + + init { + if (strides.linearSize != buffer.size) { + error("Expected buffer side of ${strides.linearSize}, but found ${buffer.size}") + } + } + + override operator fun get(index: IntArray): T = buffer[strides.offset(index)] + + override val shape: IntArray get() = strides.shape + + override fun elements(): Sequence> = strides.indices().map { + it to this[it] + } + + override fun toString(): String = StructureND.toString(this) +} + +/** + * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferND] + */ +public inline fun StructureND.mapToBuffer( + factory: BufferFactory = Buffer.Companion::auto, + crossinline transform: (T) -> R, +): BufferND { + return if (this is BufferND) + BufferND(this.strides, factory.invoke(strides.linearSize) { transform(buffer[it]) }) + else { + val strides = DefaultStrides(shape) + BufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) + } +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index b31ce3eac..78eac1809 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -3,8 +3,6 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.MutableBuffer -import space.kscience.kmath.structures.asSequence import kotlin.jvm.JvmName import kotlin.native.concurrent.ThreadLocal import kotlin.reflect.KClass @@ -56,7 +54,7 @@ public interface StructureND { /** * Indicates whether some [StructureND] is equal to another one. */ - public fun contentEquals(st1: StructureND, st2: StructureND): Boolean { + public fun contentEquals(st1: StructureND, st2: StructureND): Boolean { if (st1 === st2) return true // fast comparison of buffers if possible @@ -67,6 +65,25 @@ public interface StructureND { return st1.elements().all { (index, value) -> value == st2[index] } } + /** + * Debug output to string + */ + public fun toString(structure: StructureND<*>): String { + val bufferRepr: String = when (structure.shape.size) { + 1 -> (0 until structure.shape[0]).map { structure[it] } + .joinToString(prefix = "[", postfix = "]", separator = ", ") + 2 -> (0 until structure.shape[0]).joinToString(prefix = "[", postfix = "]", separator = ", ") { i -> + (0 until structure.shape[1]).joinToString(prefix = "[", postfix = "]", separator = ", ") { j -> + structure[i, j].toString() + } + } + else -> "..." + } + val className = structure::class.simpleName ?: "StructureND" + + return "$className(shape=${structure.shape.contentToString()}, buffer=$bufferRepr)" + } + /** * Creates a NDStructure with explicit buffer factory. * @@ -249,83 +266,6 @@ public class DefaultStrides private constructor(override val shape: IntArray) : } } -/** - * Represents [StructureND] over [Buffer]. - * - * @param T the type of items. - * @param strides The strides to access elements of [Buffer] by linear indices. - * @param buffer The underlying buffer. - */ -public open class BufferND( - public val strides: Strides, - buffer: Buffer, -) : StructureND { - - init { - if (strides.linearSize != buffer.size) { - error("Expected buffer side of ${strides.linearSize}, but found ${buffer.size}") - } - } - - public open val buffer: Buffer = buffer - - override operator fun get(index: IntArray): T = buffer[strides.offset(index)] - - override val shape: IntArray get() = strides.shape - - override fun elements(): Sequence> = strides.indices().map { - it to this[it] - } - - override fun toString(): String { - val bufferRepr: String = when (shape.size) { - 1 -> buffer.asSequence().joinToString(prefix = "[", postfix = "]", separator = ", ") - 2 -> (0 until shape[0]).joinToString(prefix = "[", postfix = "]", separator = ", ") { i -> - (0 until shape[1]).joinToString(prefix = "[", postfix = "]", separator = ", ") { j -> - val offset = strides.offset(intArrayOf(i, j)) - buffer[offset].toString() - } - } - else -> "..." - } - return "NDBuffer(shape=${shape.contentToString()}, buffer=$bufferRepr)" - } -} - -/** - * Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferND] - */ -public inline fun StructureND.mapToBuffer( - factory: BufferFactory = Buffer.Companion::auto, - crossinline transform: (T) -> R, -): BufferND { - return if (this is BufferND) - BufferND(this.strides, factory.invoke(strides.linearSize) { transform(buffer[it]) }) - else { - val strides = DefaultStrides(shape) - BufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) - } -} - -/** - * Mutable ND buffer based on linear [MutableBuffer]. - */ -public class MutableBufferND( - strides: Strides, - buffer: MutableBuffer, -) : BufferND(strides, buffer), MutableStructureND { - - init { - require(strides.linearSize == buffer.size) { - "Expected buffer side of ${strides.linearSize}, but found ${buffer.size}" - } - } - - override val buffer: MutableBuffer = super.buffer as MutableBuffer - - override operator fun set(index: IntArray, value: T): Unit = buffer.set(strides.offset(index), value) -} - public inline fun StructureND.combine( struct: StructureND, crossinline block: (T, T) -> T, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index b29181cea..7ce098ed1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -41,6 +41,9 @@ public interface Buffer { public companion object { + /** + * Check the element-by-element match of content of two buffers. + */ public fun contentEquals(first: Buffer, second: Buffer): Boolean{ if (first.size != second.size) return false for (i in first.indices) { diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 63c5cd249..139cd3cef 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -1,13 +1,13 @@ # Real number specialization module (`kmath-for-real`) - - [RealVector](src/commonMain/kotlin/kscience/kmath/real/RealVector.kt) : Numpy-like operations for Buffers/Points - - [RealMatrix](src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt) : Numpy-like operations for 2d real structures - - [grids](src/commonMain/kotlin/kscience/kmath/structures/grids.kt) : Uniform grid generators + - [DoubleVector](src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt) : Numpy-like operations for Buffers/Points + - [DoubleMatrix](src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt) : Numpy-like operations for 2d real structures + - [grids](src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt) : Uniform grid generators > #### Artifact: > -> This module artifact: `space.kscience:kmath-for-real:0.3.0-dev-2`. +> This module artifact: `space.kscience:kmath-for-real:0.3.0-dev-3`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-for-real/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-for-real/_latestVersion) > @@ -20,13 +20,10 @@ > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { -> implementation 'space.kscience:kmath-for-real:0.3.0-dev-2' +> implementation 'space.kscience:kmath-for-real:0.3.0-dev-3' > } > ``` > **Gradle Kotlin DSL:** @@ -36,12 +33,9 @@ > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { -> implementation("space.kscience:kmath-for-real:0.3.0-dev-2") +> implementation("space.kscience:kmath-for-real:0.3.0-dev-3") > } > ``` diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index 5fc6724f3..0dcaf330a 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -20,18 +20,18 @@ readme { feature( id = "DoubleVector", description = "Numpy-like operations for Buffers/Points", - ref = "src/commonMain/kotlin/kscience/kmath/real/DoubleVector.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt" ) feature( id = "DoubleMatrix", description = "Numpy-like operations for 2d real structures", - ref = "src/commonMain/kotlin/kscience/kmath/real/DoubleMatrix.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt" ) feature( id = "grids", description = "Uniform grid generators", - ref = "src/commonMain/kotlin/kscience/kmath/structures/grids.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt" ) } diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 29cc68c8e..d13c4c107 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -2,15 +2,15 @@ Functions and interpolations: - - [piecewise](Piecewise functions.) : src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt - - [polynomials](Polynomial functions.) : src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt - - [linear interpolation](Linear XY interpolator.) : src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt - - [spline interpolation](Cubic spline XY interpolator.) : src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt + - [piecewise](Piecewise functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt + - [polynomials](Polynomial functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt + - [linear interpolation](Linear XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt + - [spline interpolation](Cubic spline XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt > #### Artifact: > -> This module artifact: `space.kscience:kmath-functions:0.3.0-dev-2`. +> This module artifact: `space.kscience:kmath-functions:0.3.0-dev-3`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-functions/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-functions/_latestVersion) > @@ -23,13 +23,10 @@ Functions and interpolations: > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { -> implementation 'space.kscience:kmath-functions:0.3.0-dev-2' +> implementation 'space.kscience:kmath-functions:0.3.0-dev-3' > } > ``` > **Gradle Kotlin DSL:** @@ -39,12 +36,9 @@ Functions and interpolations: > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { -> implementation("space.kscience:kmath-functions:0.3.0-dev-2") +> implementation("space.kscience:kmath-functions:0.3.0-dev-3") > } > ``` diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 067dbd9b3..51fc75501 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -13,12 +13,12 @@ readme { maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) - feature("piecewise", "src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt", "Piecewise functions.") - feature("polynomials", "src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt", "Polynomial functions.") + feature("piecewise", "src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt", "Piecewise functions.") + feature("polynomials", "src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt", "Polynomial functions.") feature("linear interpolation", - "src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt", + "src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt", "Linear XY interpolator.") feature("spline interpolation", - "src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt", + "src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt", "Cubic spline XY interpolator.") } \ No newline at end of file diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 08f0ae541..2771722eb 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -2,14 +2,14 @@ This subproject implements the following features: - - [nd4jarraystructure](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray - - [nd4jarrayrings](src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long - - [nd4jarrayfields](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double + - [nd4jarraystructure](#) : NDStructure wrapper for INDArray + - [nd4jarrayrings](#) : Rings over Nd4jArrayStructure of Int and Long + - [nd4jarrayfields](#) : Fields over Nd4jArrayStructure of Float and Double > #### Artifact: > -> This module artifact: `space.kscience:kmath-nd4j:0.3.0-dev-2`. +> This module artifact: `space.kscience:kmath-nd4j:0.3.0-dev-3`. > > Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-nd4j/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-nd4j/_latestVersion) > @@ -22,13 +22,10 @@ This subproject implements the following features: > maven { url 'https://repo.kotlin.link' } > maven { url 'https://dl.bintray.com/hotkeytlt/maven' } > maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap ->// Uncomment if repo.kotlin.link is unavailable ->// maven { url 'https://dl.bintray.com/mipt-npm/kscience' } ->// maven { url 'https://dl.bintray.com/mipt-npm/dev' } > } > > dependencies { -> implementation 'space.kscience:kmath-nd4j:0.3.0-dev-2' +> implementation 'space.kscience:kmath-nd4j:0.3.0-dev-3' > } > ``` > **Gradle Kotlin DSL:** @@ -38,13 +35,10 @@ This subproject implements the following features: > maven("https://repo.kotlin.link") > maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap > maven("https://dl.bintray.com/hotkeytlt/maven") // required for a ->// Uncomment if repo.kotlin.link is unavailable ->// maven("https://dl.bintray.com/mipt-npm/kscience") ->// maven("https://dl.bintray.com/mipt-npm/dev") > } > > dependencies { -> implementation("space.kscience:kmath-nd4j:0.3.0-dev-2") +> implementation("space.kscience:kmath-nd4j:0.3.0-dev-3") > } > ``` @@ -57,7 +51,7 @@ import org.nd4j.linalg.factory.* import scientifik.kmath.nd4j.* import scientifik.kmath.structures.* -val array = Nd4j.ones(2, 2).asRealStructure() +val array = Nd4j.ones(2, 2).asDoubleStructure() println(array[0, 0]) // 1.0 array[intArrayOf(0, 0)] = 24.0 println(array[0, 0]) // 24.0 @@ -70,8 +64,8 @@ import org.nd4j.linalg.factory.* import scientifik.kmath.nd4j.* import scientifik.kmath.operations.* -val field = RealNd4jArrayField(intArrayOf(2, 2)) -val array = Nd4j.rand(2, 2).asRealStructure() +val field = DoubleNd4jArrayField(intArrayOf(2, 2)) +val array = Nd4j.rand(2, 2).asDoubleStructure() val res = field { (25.0 / array + 20) * 4 diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index c801f8e51..2954a1e65 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -19,19 +19,16 @@ readme { feature( id = "nd4jarraystructure", - description = "NDStructure wrapper for INDArray", - ref = "src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt" + description = "NDStructure wrapper for INDArray" ) feature( id = "nd4jarrayrings", - description = "Rings over Nd4jArrayStructure of Int and Long", - ref = "src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt" + description = "Rings over Nd4jArrayStructure of Int and Long" ) feature( id = "nd4jarrayfields", - description = "Fields over Nd4jArrayStructure of Float and Double", - ref = "src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt" + description = "Fields over Nd4jArrayStructure of Float and Double" ) } From efb23591a9efebe3bf86b2757ac482032b5047a7 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 17 Mar 2021 07:36:35 +0000 Subject: [PATCH 108/393] Added squeeze --- .../space/kscience/kmath/tensors/DoubleTensorAlgebra.kt | 4 ++++ .../kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt | 2 ++ 2 files changed, 6 insertions(+) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 888f12923..675be2f33 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -266,6 +266,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra DoubleTensorAlgebra(block: DoubleTensorAlgebra.() -> R): R = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 0af757d1a..b1adf2962 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -86,4 +86,6 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.flatten.html#torch.flatten public fun TensorType.flatten(startDim: Int, endDim: Int): TensorType + //https://pytorch.org/docs/stable/generated/torch.squeeze.html + public fun TensorType.squeeze(dim: Int): TensorType } From 1fa0da2810d69aa6d9dac669b4ebc353dd5265d1 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 17 Mar 2021 17:53:14 +0300 Subject: [PATCH 109/393] complete lu and matrix mapping --- .../kscience/kmath/tensors/BufferedTensor.kt | 95 +++++++++---------- .../tensors/DoubleLinearOpsTensorAlgebra.kt | 83 ++++++++-------- .../kscience/kmath/tensors/TensorAlgebra.kt | 2 +- 3 files changed, 85 insertions(+), 95 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index c9a401ad5..c48e47f4c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.nd.* import space.kscience.kmath.structures.* @@ -29,59 +31,50 @@ public open class BufferedTensor( override fun hashCode(): Int = 0 + // todo rename to vector + public inline fun forEachVector(vectorAction : (MutableStructure1D) -> Unit): Unit { + check(shape.size >= 1) {"todo"} + val vectorOffset = strides.strides[0] + val vectorShape = intArrayOf(shape.last()) + for (offset in 0 until numel step vectorOffset) { + val vector = BufferedTensor(vectorShape, buffer, offset).as1D() + vectorAction(vector) + } + } + + public inline fun forEachMatrix(matrixAction : (MutableStructure2D) -> Unit): Unit { + check(shape.size >= 2) {"todo"} + val matrixOffset = strides.strides[1] + val matrixShape = intArrayOf(shape[shape.size - 2], shape.last()) //todo better way? + for (offset in 0 until numel step matrixOffset) { + val matrix = BufferedTensor(matrixShape, buffer, offset).as2D() + matrixAction(matrix) + } + } + // todo remove code copy-pasting + + public fun vectorSequence(): Sequence> = sequence { + check(shape.size >= 1) {"todo"} + val vectorOffset = strides.strides[0] + val vectorShape = intArrayOf(shape.last()) + for (offset in 0 until numel step vectorOffset) { + val vector = BufferedTensor(vectorShape, buffer, offset).as1D() + yield(vector) + } + } + + public fun matrixSequence(): Sequence> = sequence { + check(shape.size >= 2) {"todo"} + val matrixOffset = strides.strides[1] + val matrixShape = intArrayOf(shape[shape.size - 2], shape.last()) //todo better way? + for (offset in 0 until numel step matrixOffset) { + val matrix = BufferedTensor(matrixShape, buffer, offset).as2D() + yield(matrix) + } + } + } -/* -//todo make generator mb nextMatrixIndex? -public class InnerMatrix(private val tensor: BufferedTensor){ - private var offset: Int = 0 - private val n : Int = tensor.shape.size - //stride? - private val step = tensor.shape[n - 1] * tensor.shape[n - 2] - - public operator fun get(i: Int, j: Int): T { - val index = tensor.strides.index(offset) - index[n - 2] = i - index[n - 1] = j - return tensor[index] - } - - public operator fun set(i: Int, j: Int, value: T): Unit { - val index = tensor.strides.index(offset) - index[n - 2] = i - index[n - 1] = j - tensor[index] = value - } - - public fun makeStep(){ - offset += step - } -} - -public class InnerVector(private val tensor: BufferedTensor){ - private var offset: Int = 0 - private val n : Int = tensor.shape.size - //stride? - private val step = tensor.shape[n - 1] - - public operator fun get(i: Int): T { - val index = tensor.strides.index(offset) - index[n - 1] = i - return tensor[index] - } - - public operator fun set(i: Int, value: T): Unit { - val index = tensor.strides.index(offset) - index[n - 1] = i - tensor[index] = value - } - - public fun makeStep(){ - offset += step - } -} -//todo default buffer = arrayOf(0)??? - */ public class IntTensor( shape: IntArray, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt index 689eda9e0..3f44305b1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt @@ -9,27 +9,21 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.lu(): Pair { - /* + // todo checks + val luTensor = this.copy() - val lu = InnerMatrix(luTensor) - //stride TODO!!! move to generator? - var matCnt = 1 - for (i in 0 until this.shape.size - 2) { - matCnt *= this.shape[i] - } + val n = this.shape.size - val m = this.shape[n - 1] - val pivotsShape = IntArray(n - 1) { i -> - this.shape[i] - } + val m = this.shape.last() + val pivotsShape = IntArray(n - 1) { i -> this.shape[i] } val pivotsTensor = IntTensor( pivotsShape, - IntArray(matCnt * m) { 0 } + IntArray(pivotsShape.reduce(Int::times)) { 0 } //todo default??? ) - val pivot = InnerVector(pivotsTensor) - for (i in 0 until matCnt) { - for (row in 0 until m) pivot[row] = row + + for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())){ + for (row in 0 until m) pivots[row] = row for (i in 0 until m) { var maxA = -1.0 @@ -47,9 +41,9 @@ public class DoubleLinearOpsTensorAlgebra : if (iMax != i) { - val j = pivot[i] - pivot[i] = pivot[iMax] - pivot[iMax] = j + val j = pivots[i] + pivots[i] = pivots[iMax] + pivots[iMax] = j for (k in 0 until m) { val tmp = lu[i, k] @@ -66,42 +60,45 @@ public class DoubleLinearOpsTensorAlgebra : } } } - lu.makeStep() - pivot.makeStep() } - return Pair(luTensor, pivotsTensor)*/ - TODO("Andrei, use view, get, as2D, as1D") + return Pair(luTensor, pivotsTensor) + } - override fun luPivot(lu: DoubleTensor, pivots: IntTensor): Triple { - /* - // todo checks - val n = lu.shape[0] - val p = lu.zeroesLike() - pivots.buffer.unsafeToIntArray().forEachIndexed { i, pivot -> - p[i, pivot] = 1.0 + override fun luPivot(luTensor: DoubleTensor, pivotsTensor: IntTensor): Triple { + //todo checks + val n = luTensor.shape.last() + val pTensor = luTensor.zeroesLike() + for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.vectorSequence())){ + for (i in 0 until n){ + p[i, pivot[i]] = 1.0 + } } - val l = lu.zeroesLike() - val u = lu.zeroesLike() - for (i in 0 until n) { - for (j in 0 until n) { - if (i == j) { - l[i, j] = 1.0 - } - if (j < i) { - l[i, j] = lu[i, j] - } - if (j >= i) { - u[i, j] = lu[i, j] + val lTensor = luTensor.zeroesLike() + val uTensor = luTensor.zeroesLike() + + for ((pairLU, lu) in lTensor.matrixSequence().zip(uTensor.matrixSequence()).zip(luTensor.matrixSequence())){ + val (l, u) = pairLU + for (i in 0 until n) { + for (j in 0 until n) { + if (i == j) { + l[i, j] = 1.0 + } + if (j < i) { + l[i, j] = lu[i, j] + } + if (j >= i) { + u[i, j] = lu[i, j] + } } } } - return Triple(p, l, u)*/ - TODO("Andrei, first we need implement get(Int)") + return Triple(pTensor, lTensor, uTensor) + } override fun DoubleTensor.cholesky(): DoubleTensor { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index b1adf2962..7ec920d88 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -5,7 +5,7 @@ public interface TensorAlgebra> { public fun zeros(shape: IntArray): TensorType - public fun TensorType.zeroesLike(): TensorType + public fun TensorType.zeroesLike(): TensorType // mb it shouldn't be tensor but algebra method (like in numpy/torch) ? public fun ones(shape: IntArray): TensorType public fun TensorType.onesLike(): TensorType From 6375cb5fd8cd0e50d6f236707e5f5818e104de64 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 17 Mar 2021 23:11:26 +0700 Subject: [PATCH 110/393] Some adjustments to the EJML module --- README.md | 12 ++-- kmath-ast/README.md | 2 +- kmath-core/README.md | 4 +- kmath-ejml/README.md | 43 ++++++++++++++ kmath-ejml/build.gradle.kts | 29 ++++++++-- kmath-ejml/docs/README-TEMPLATE.md | 7 +++ .../kscience/kmath/ejml/EjmlLinearSpace.kt | 56 ++++++++++++------- .../space/kscience/kmath/ejml/EjmlMatrix.kt | 2 +- .../space/kscience/kmath/ejml/EjmlVector.kt | 2 +- 9 files changed, 122 insertions(+), 35 deletions(-) create mode 100644 kmath-ejml/README.md create mode 100644 kmath-ejml/docs/README-TEMPLATE.md diff --git a/README.md b/README.md index 2aaeb3150..cc9439d27 100644 --- a/README.md +++ b/README.md @@ -120,10 +120,10 @@ KMath is a modular library. Different modules provide different features with di > > **Features:** > - [algebras](kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields. -> - [nd](kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt) : Many-dimensional structures and operations on them. +> - [nd](kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt) : Many-dimensional structures and operations on them. > - [linear](kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition. -> - [buffers](kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt) : One-dimensional structure -> - [expressions](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of +> - [buffers](kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffers.kt) : One-dimensional structure +> - [expressions](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high performance calculations to code generation. > - [domains](kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains) : Domains @@ -206,9 +206,9 @@ One can still use generic algebras though. > **Maturity**: EXPERIMENTAL > > **Features:** -> - [nd4jarraystructure](kmath-nd4j/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray -> - [nd4jarrayrings](kmath-nd4j/src/commonMain/kotlin/space/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long -> - [nd4jarrayfields](kmath-nd4j/src/commonMain/kotlin/space/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double +> - [nd4jarraystructure](kmath-nd4j/#) : NDStructure wrapper for INDArray +> - [nd4jarrayrings](kmath-nd4j/#) : Rings over Nd4jArrayStructure of Int and Long +> - [nd4jarrayfields](kmath-nd4j/#) : Fields over Nd4jArrayStructure of Float and Double
diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 4c79b5b36..ee14604d2 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -58,7 +58,7 @@ For example, the following builder: DoubleField.mstInField { symbol("x") + 2 }.compile() ``` -… leads to generation of bytecode, which can be decompiled to the following Java class: +… leads to generation of bytecode, which can be decompiled to the following Java class: ```java package space.kscience.kmath.asm.generated; diff --git a/kmath-core/README.md b/kmath-core/README.md index dd54b7aeb..4e4b5273d 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -3,10 +3,10 @@ The core features of KMath: - [algebras](src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields. - - [nd](src/commonMain/kotlin/space/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures and operations on them. + - [nd](src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt) : Many-dimensional structures and operations on them. - [linear](src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition. - [buffers](src/commonMain/kotlin/space/kscience/kmath/structures/Buffers.kt) : One-dimensional structure - - [expressions](src/commonMain/kotlin/space/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of + - [expressions](src/commonMain/kotlin/space/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high performance calculations to code generation. - [domains](src/commonMain/kotlin/space/kscience/kmath/domains) : Domains diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md new file mode 100644 index 000000000..1081b2b7f --- /dev/null +++ b/kmath-ejml/README.md @@ -0,0 +1,43 @@ +# ejml-simple support (`kmath-ejml`) + +This subproject implements the following features: + + - [ejml-vector](src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix. + - [ejml-matrix](src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix. + - [ejml-linear-space](src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix. + + +> #### Artifact: +> +> This module artifact: `space.kscience:kmath-ejml:0.3.0-dev-3`. +> +> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-ejml/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-ejml/_latestVersion) +> +> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-ejml/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-ejml/_latestVersion) +> +> **Gradle:** +> +> ```gradle +> repositories { +> maven { url 'https://repo.kotlin.link' } +> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } +> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap +> } +> +> dependencies { +> implementation 'space.kscience:kmath-ejml:0.3.0-dev-3' +> } +> ``` +> **Gradle Kotlin DSL:** +> +> ```kotlin +> repositories { +> maven("https://repo.kotlin.link") +> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap +> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a +> } +> +> dependencies { +> implementation("space.kscience:kmath-ejml:0.3.0-dev-3") +> } +> ``` diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index 1ce2291c4..5091139ac 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -1,12 +1,33 @@ +import ru.mipt.npm.gradle.Maturity + plugins { id("ru.mipt.npm.gradle.jvm") } dependencies { - implementation("org.ejml:ejml-simple:0.39") - implementation(project(":kmath-core")) + api("org.ejml:ejml-simple:0.40") + api(project(":kmath-core")) } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE -} \ No newline at end of file + maturity = Maturity.PROTOTYPE + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + + feature( + id = "ejml-vector", + description = "The Point implementation using SimpleMatrix.", + ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt" + ) + + feature( + id = "ejml-matrix", + description = "The Matrix implementation using SimpleMatrix.", + ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt" + ) + + feature( + id = "ejml-linear-space", + description = "The LinearSpace implementation using SimpleMatrix.", + ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt" + ) +} diff --git a/kmath-ejml/docs/README-TEMPLATE.md b/kmath-ejml/docs/README-TEMPLATE.md new file mode 100644 index 000000000..c53f4a81c --- /dev/null +++ b/kmath-ejml/docs/README-TEMPLATE.md @@ -0,0 +1,7 @@ +# ejml-simple support (`kmath-ejml`) + +This subproject implements the following features: + +${features} + +${artifact} diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index a82fe933e..6fc0a049c 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -14,10 +14,13 @@ import kotlin.reflect.cast * Represents context of basic operations operating with [EjmlMatrix]. * * @author Iaroslav Postovalov + * @author Alexander Nozik */ public object EjmlLinearSpace : LinearSpace { - - override val elementAlgebra: DoubleField get() = DoubleField + /** + * The [DoubleField] reference. + */ + public override val elementAlgebra: DoubleField get() = DoubleField /** * Converts this matrix to EJML one. @@ -38,14 +41,17 @@ public object EjmlLinearSpace : LinearSpace { }) } - override fun buildMatrix(rows: Int, columns: Int, initializer: DoubleField.(i: Int, j: Int) -> Double): EjmlMatrix = - EjmlMatrix(SimpleMatrix(rows, columns).also { - (0 until rows).forEach { row -> - (0 until columns).forEach { col -> it[row, col] = DoubleField.initializer(row, col) } - } - }) + public override fun buildMatrix( + rows: Int, + columns: Int, + initializer: DoubleField.(i: Int, j: Int) -> Double, + ): EjmlMatrix = EjmlMatrix(SimpleMatrix(rows, columns).also { + (0 until rows).forEach { row -> + (0 until columns).forEach { col -> it[row, col] = DoubleField.initializer(row, col) } + } + }) - override fun buildVector(size: Int, initializer: DoubleField.(Int) -> Double): Point = + public override fun buildVector(size: Int, initializer: DoubleField.(Int) -> Double): Point = EjmlVector(SimpleMatrix(size, 1).also { (0 until it.numRows()).forEach { row -> it[row, 0] = DoubleField.initializer(row) } }) @@ -53,7 +59,7 @@ public object EjmlLinearSpace : LinearSpace { private fun SimpleMatrix.wrapMatrix() = EjmlMatrix(this) private fun SimpleMatrix.wrapVector() = EjmlVector(this) - override fun Matrix.unaryMinus(): Matrix = this * (-1.0) + public override fun Matrix.unaryMinus(): Matrix = this * (-1.0) public override fun Matrix.dot(other: Matrix): EjmlMatrix = EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) @@ -67,29 +73,29 @@ public object EjmlLinearSpace : LinearSpace { public override operator fun Matrix.times(value: Double): EjmlMatrix = toEjml().origin.scale(value).wrapMatrix() - override fun Point.unaryMinus(): EjmlVector = + public override fun Point.unaryMinus(): EjmlVector = toEjml().origin.negative().wrapVector() - override fun Matrix.plus(other: Matrix): EjmlMatrix = + public override fun Matrix.plus(other: Matrix): EjmlMatrix = (toEjml().origin + other.toEjml().origin).wrapMatrix() - override fun Point.plus(other: Point): EjmlVector = + public override fun Point.plus(other: Point): EjmlVector = (toEjml().origin + other.toEjml().origin).wrapVector() - override fun Point.minus(other: Point): EjmlVector = + public override fun Point.minus(other: Point): EjmlVector = (toEjml().origin - other.toEjml().origin).wrapVector() - override fun Double.times(m: Matrix): EjmlMatrix = + public override fun Double.times(m: Matrix): EjmlMatrix = m.toEjml().origin.scale(this).wrapMatrix() - override fun Point.times(value: Double): EjmlVector = + public override fun Point.times(value: Double): EjmlVector = toEjml().origin.scale(value).wrapVector() - override fun Double.times(v: Point): EjmlVector = + public override fun Double.times(v: Point): EjmlVector = v.toEjml().origin.scale(this).wrapVector() @UnstableKMathAPI - override fun getFeature(structure: Matrix, type: KClass): F? { + public override fun getFeature(structure: Matrix, type: KClass): F? { //Return the feature if it is intrinsic to the structure structure.getFeature(type)?.let { return it } @@ -160,7 +166,7 @@ public object EjmlLinearSpace : LinearSpace { } /** - * Solves for X in the following equation: x = a^-1*b, where 'a' is base matrix and 'b' is an n by p matrix. + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. * * @param a the base matrix. * @param b n by p matrix. @@ -171,7 +177,7 @@ public fun EjmlLinearSpace.solve(a: Matrix, b: Matrix): EjmlMatr EjmlMatrix(a.toEjml().origin.solve(b.toEjml().origin)) /** - * Solves for X in the following equation: x = a^(-1)*b, where 'a' is base matrix and 'b' is an n by p matrix. + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. * * @param a the base matrix. * @param b n by p vector. @@ -181,7 +187,17 @@ public fun EjmlLinearSpace.solve(a: Matrix, b: Matrix): EjmlMatr public fun EjmlLinearSpace.solve(a: Matrix, b: Point): EjmlVector = EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) +/** + * Inverts this matrix. + * + * @author Alexander Nozik + */ @OptIn(UnstableKMathAPI::class) public fun EjmlMatrix.inverted(): EjmlMatrix = getFeature>()!!.inverse as EjmlMatrix +/** + * Inverts the given matrix. + * + * @author Alexander Nozik + */ public fun EjmlLinearSpace.inverse(matrix: Matrix): Matrix = matrix.toEjml().inverted() \ No newline at end of file diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index 712c2a42c..10afd6ec2 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -4,7 +4,7 @@ import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.Matrix /** - * Represents featured matrix over EJML [SimpleMatrix]. + * The matrix implementation over EJML [SimpleMatrix]. * * @property origin the underlying [SimpleMatrix]. * @author Iaroslav Postovalov diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt index c7f87675d..2c8d2edd4 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.linear.Point * @property origin the underlying [SimpleMatrix]. * @author Iaroslav Postovalov */ -public class EjmlVector internal constructor(public val origin: SimpleMatrix) : Point { +public inline class EjmlVector internal constructor(public val origin: SimpleMatrix) : Point { public override val size: Int get() = origin.numRows() From 88d0c19a741f32145877c65d1cf7f70ff20b9ade Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 19 Mar 2021 11:07:27 +0300 Subject: [PATCH 111/393] Refactor structure features. Basic curve fitting --- build.gradle.kts | 6 +- .../kmath/commons/fit/fitWithAutoDiff.kt | 8 +- .../kscience/kmath/commons/linear/CMMatrix.kt | 3 +- ...timizationProblem.kt => CMOptimization.kt} | 42 +++--- .../kmath/commons/optimization/cmFit.kt | 22 ++-- .../commons/optimization/OptimizeTest.kt | 4 +- kmath-core/api/kmath-core.api | 9 +- .../kscience/kmath/linear/LinearSpace.kt | 4 +- .../kscience/kmath/linear/MatrixFeatures.kt | 4 +- .../kscience/kmath/linear/MatrixWrapper.kt | 3 +- .../space/kscience/kmath/nd/AlgebraND.kt | 5 +- .../space/kscience/kmath/nd/Structure1D.kt | 2 + .../space/kscience/kmath/nd/Structure2D.kt | 2 +- .../space/kscience/kmath/nd/StructureND.kt | 6 +- .../kmath/chains/BlockingDoubleChain.kt | 2 +- .../kscience/kmath/ejml/EjmlLinearSpace.kt | 3 +- .../kotlin/space/kscience/kmath/real/grids.kt | 74 ++++++----- kmath-stat/build.gradle.kts | 8 -- .../kscience/kmath/optimization/DataFit.kt | 17 +++ .../optimization/FunctionOptimization.kt | 122 ++++++++++++++++++ .../kmath/optimization/Optimization.kt | 44 +++++++ .../space/kscience/kmath/stat/Fitting.kt | 63 --------- .../kmath/stat/OptimizationProblem.kt | 88 ------------- .../space/kscience/kmath/stat/RandomChain.kt | 2 +- .../kscience/kmath/stat/distributions.kt | 25 ++-- 25 files changed, 311 insertions(+), 257 deletions(-) rename kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/{CMOptimizationProblem.kt => CMOptimization.kt} (75%) create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/DataFit.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Fitting.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt diff --git a/build.gradle.kts b/build.gradle.kts index 5f1a8b88a..9570d7744 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,3 @@ -import ru.mipt.npm.gradle.KSciencePublishingPlugin - plugins { id("ru.mipt.npm.gradle.project") } @@ -20,11 +18,11 @@ allprojects { } group = "space.kscience" - version = "0.3.0-dev-3" + version = "0.3.0-dev-4" } subprojects { - if (name.startsWith("kmath")) apply() + if (name.startsWith("kmath")) apply(plugin = "maven-publish") } readme { diff --git a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt index ef0c29a2d..6141a1058 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -8,10 +8,14 @@ import kscience.plotly.models.TraceValues import space.kscience.kmath.commons.optimization.chiSquared import space.kscience.kmath.commons.optimization.minimize import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.optimization.FunctionOptimization +import space.kscience.kmath.optimization.OptimizationResult import space.kscience.kmath.real.DoubleVector import space.kscience.kmath.real.map import space.kscience.kmath.real.step -import space.kscience.kmath.stat.* +import space.kscience.kmath.stat.Distribution +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.normal import space.kscience.kmath.structures.asIterable import space.kscience.kmath.structures.toList import kotlin.math.pow @@ -58,7 +62,7 @@ fun main() { val yErr = y.map { sqrt(it) }//RealVector.same(x.size, sigma) // compute differentiable chi^2 sum for given model ax^2 + bx + c - val chi2 = Fitting.chiSquared(x, y, yErr) { x1 -> + val chi2 = FunctionOptimization.chiSquared(x, y, yErr) { x1 -> //bind variables to autodiff context val a = bind(a) val b = bind(b) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index 89e9649e9..80929e6b9 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -3,6 +3,7 @@ package space.kscience.kmath.commons.linear import org.apache.commons.math3.linear.* import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.DoubleBuffer import kotlin.reflect.KClass @@ -89,7 +90,7 @@ public object CMLinearSpace : LinearSpace { v * this @UnstableKMathAPI - override fun getFeature(structure: Matrix, type: KClass): F? { + override fun getFeature(structure: Matrix, type: KClass): F? { //Return the feature if it is intrinsic to the structure structure.getFeature(type)?.let { return it } diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt similarity index 75% rename from kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt rename to kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt index 13a10475f..6200b61a9 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt @@ -10,21 +10,25 @@ import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.AbstractSimplex import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer import space.kscience.kmath.expressions.* -import space.kscience.kmath.stat.OptimizationFeature -import space.kscience.kmath.stat.OptimizationProblem -import space.kscience.kmath.stat.OptimizationProblemFactory -import space.kscience.kmath.stat.OptimizationResult +import space.kscience.kmath.optimization.FunctionOptimization +import space.kscience.kmath.optimization.OptimizationFeature +import space.kscience.kmath.optimization.OptimizationProblemFactory +import space.kscience.kmath.optimization.OptimizationResult import kotlin.reflect.KClass public operator fun PointValuePair.component1(): DoubleArray = point public operator fun PointValuePair.component2(): Double = value -public class CMOptimizationProblem(override val symbols: List) : - OptimizationProblem, SymbolIndexer, OptimizationFeature { +public class CMOptimization( + override val symbols: List, +) : FunctionOptimization, SymbolIndexer, OptimizationFeature { private val optimizationData: HashMap, OptimizationData> = HashMap() - private var optimizatorBuilder: (() -> MultivariateOptimizer)? = null - public var convergenceChecker: ConvergenceChecker = SimpleValueChecker(DEFAULT_RELATIVE_TOLERANCE, - DEFAULT_ABSOLUTE_TOLERANCE, DEFAULT_MAX_ITER) + private var optimizerBuilder: (() -> MultivariateOptimizer)? = null + public var convergenceChecker: ConvergenceChecker = SimpleValueChecker( + DEFAULT_RELATIVE_TOLERANCE, + DEFAULT_ABSOLUTE_TOLERANCE, + DEFAULT_MAX_ITER + ) public fun addOptimizationData(data: OptimizationData) { optimizationData[data::class] = data @@ -57,8 +61,8 @@ public class CMOptimizationProblem(override val symbols: List) : } } addOptimizationData(gradientFunction) - if (optimizatorBuilder == null) { - optimizatorBuilder = { + if (optimizerBuilder == null) { + optimizerBuilder = { NonLinearConjugateGradientOptimizer( NonLinearConjugateGradientOptimizer.Formula.FLETCHER_REEVES, convergenceChecker @@ -70,8 +74,8 @@ public class CMOptimizationProblem(override val symbols: List) : public fun simplex(simplex: AbstractSimplex) { addOptimizationData(simplex) //Set optimization builder to simplex if it is not present - if (optimizatorBuilder == null) { - optimizatorBuilder = { SimplexOptimizer(convergenceChecker) } + if (optimizerBuilder == null) { + optimizerBuilder = { SimplexOptimizer(convergenceChecker) } } } @@ -84,7 +88,7 @@ public class CMOptimizationProblem(override val symbols: List) : } public fun optimizer(block: () -> MultivariateOptimizer) { - optimizatorBuilder = block + optimizerBuilder = block } override fun update(result: OptimizationResult) { @@ -92,19 +96,19 @@ public class CMOptimizationProblem(override val symbols: List) : } override fun optimize(): OptimizationResult { - val optimizer = optimizatorBuilder?.invoke() ?: error("Optimizer not defined") + val optimizer = optimizerBuilder?.invoke() ?: error("Optimizer not defined") val (point, value) = optimizer.optimize(*optimizationData.values.toTypedArray()) return OptimizationResult(point.toMap(), value, setOf(this)) } - public companion object : OptimizationProblemFactory { + public companion object : OptimizationProblemFactory { public const val DEFAULT_RELATIVE_TOLERANCE: Double = 1e-4 public const val DEFAULT_ABSOLUTE_TOLERANCE: Double = 1e-4 public const val DEFAULT_MAX_ITER: Int = 1000 - override fun build(symbols: List): CMOptimizationProblem = CMOptimizationProblem(symbols) + override fun build(symbols: List): CMOptimization = CMOptimization(symbols) } } -public fun CMOptimizationProblem.initialGuess(vararg pairs: Pair): Unit = initialGuess(pairs.toMap()) -public fun CMOptimizationProblem.simplexSteps(vararg pairs: Pair): Unit = simplexSteps(pairs.toMap()) +public fun CMOptimization.initialGuess(vararg pairs: Pair): Unit = initialGuess(pairs.toMap()) +public fun CMOptimization.simplexSteps(vararg pairs: Pair): Unit = simplexSteps(pairs.toMap()) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt index 5ecd5b756..384414e6d 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt @@ -6,16 +6,16 @@ import space.kscience.kmath.commons.expressions.DerivativeStructureField import space.kscience.kmath.expressions.DifferentiableExpression import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.stat.Fitting -import space.kscience.kmath.stat.OptimizationResult -import space.kscience.kmath.stat.optimizeWith +import space.kscience.kmath.optimization.FunctionOptimization +import space.kscience.kmath.optimization.OptimizationResult +import space.kscience.kmath.optimization.optimizeWith import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer /** * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation */ -public fun Fitting.chiSquared( +public fun FunctionOptimization.Companion.chiSquared( x: Buffer, y: Buffer, yErr: Buffer, @@ -25,7 +25,7 @@ public fun Fitting.chiSquared( /** * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation */ -public fun Fitting.chiSquared( +public fun FunctionOptimization.Companion.chiSquared( x: Iterable, y: Iterable, yErr: Iterable, @@ -43,23 +43,23 @@ public fun Fitting.chiSquared( */ public fun Expression.optimize( vararg symbols: Symbol, - configuration: CMOptimizationProblem.() -> Unit, -): OptimizationResult = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) + configuration: CMOptimization.() -> Unit, +): OptimizationResult = optimizeWith(CMOptimization, symbols = symbols, configuration) /** * Optimize differentiable expression */ public fun DifferentiableExpression>.optimize( vararg symbols: Symbol, - configuration: CMOptimizationProblem.() -> Unit, -): OptimizationResult = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) + configuration: CMOptimization.() -> Unit, +): OptimizationResult = optimizeWith(CMOptimization, symbols = symbols, configuration) public fun DifferentiableExpression>.minimize( vararg startPoint: Pair, - configuration: CMOptimizationProblem.() -> Unit = {}, + configuration: CMOptimization.() -> Unit = {}, ): OptimizationResult { require(startPoint.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = CMOptimizationProblem(startPoint.map { it.first }).apply(configuration) + val problem = CMOptimization(startPoint.map { it.first }).apply(configuration) problem.diffExpression(this) problem.initialGuess(startPoint.toMap()) problem.goal(GoalType.MINIMIZE) diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt index d29934a4d..cbbe1457e 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -3,8 +3,8 @@ package space.kscience.kmath.commons.optimization import org.junit.jupiter.api.Test import space.kscience.kmath.commons.expressions.DerivativeStructureExpression import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.optimization.FunctionOptimization import space.kscience.kmath.stat.Distribution -import space.kscience.kmath.stat.Fitting import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.stat.normal import kotlin.math.pow @@ -55,7 +55,7 @@ internal class OptimizeTest { val yErr = List(x.size) { sigma } - val chi2 = Fitting.chiSquared(x, y, yErr) { x1 -> + val chi2 = FunctionOptimization.chiSquared(x, y, yErr) { x1 -> val cWithDefault = bindSymbolOrNull(c) ?: one bind(a) * x1.pow(2) + bind(b) * x1 + cWithDefault } diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 04325379e..8c62198cd 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -575,7 +575,7 @@ public final class space/kscience/kmath/linear/MatrixBuilderKt { public static final fun row (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; } -public abstract interface class space/kscience/kmath/linear/MatrixFeature { +public abstract interface class space/kscience/kmath/linear/MatrixFeature : space/kscience/kmath/nd/StructureFeature { } public final class space/kscience/kmath/linear/MatrixFeaturesKt { @@ -1060,11 +1060,15 @@ public final class space/kscience/kmath/nd/Strides$DefaultImpls { } public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/StructureND, space/kscience/kmath/structures/Buffer { + public static final field Companion Lspace/kscience/kmath/nd/Structure1D$Companion; public abstract fun get ([I)Ljava/lang/Object; public abstract fun getDimension ()I public abstract fun iterator ()Ljava/util/Iterator; } +public final class space/kscience/kmath/nd/Structure1D$Companion { +} + public final class space/kscience/kmath/nd/Structure1D$DefaultImpls { public static fun get (Lspace/kscience/kmath/nd/Structure1D;[I)Ljava/lang/Object; public static fun getDimension (Lspace/kscience/kmath/nd/Structure1D;)I @@ -1104,6 +1108,9 @@ public final class space/kscience/kmath/nd/Structure2DKt { public static final fun as2D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure2D; } +public abstract interface class space/kscience/kmath/nd/StructureFeature { +} + public abstract interface class space/kscience/kmath/nd/StructureND { public static final field Companion Lspace/kscience/kmath/nd/StructureND$Companion; public abstract fun elements ()Lkotlin/sequences/Sequence; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 6a587270b..dfc4c7c9b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -164,7 +164,7 @@ public interface LinearSpace> { * @return a feature object or `null` if it isn't present. */ @UnstableKMathAPI - public fun getFeature(structure: Matrix, type: KClass): F? = structure.getFeature(type) + public fun getFeature(structure: Matrix, type: KClass): F? = structure.getFeature(type) public companion object { @@ -194,7 +194,7 @@ public interface LinearSpace> { * @return a feature object or `null` if it isn't present. */ @UnstableKMathAPI -public inline fun LinearSpace.getFeature(structure: Matrix): F? = +public inline fun LinearSpace.getFeature(structure: Matrix): F? = getFeature(structure, F::class) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt index 6b97e89ef..30e3daa7a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt @@ -1,10 +1,12 @@ package space.kscience.kmath.linear +import space.kscience.kmath.nd.StructureFeature + /** * A marker interface representing some properties of matrices or additional transformations of them. Features are used * to optimize matrix operations performance in some cases or retrieve the APIs. */ -public interface MatrixFeature +public interface MatrixFeature: StructureFeature /** * Matrices with this feature are considered to have only diagonal non-null elements. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt index 868f74cc6..def3b87f7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.linear import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.nd.getFeature import space.kscience.kmath.operations.Ring import kotlin.reflect.KClass @@ -20,7 +21,7 @@ public class MatrixWrapper internal constructor( */ @UnstableKMathAPI @Suppress("UNCHECKED_CAST") - override fun getFeature(type: KClass): T? = features.singleOrNull { type.isInstance(it) } as? T + override fun getFeature(type: KClass): F? = features.singleOrNull { type.isInstance(it) } as? F ?: origin.getFeature(type) override fun toString(): String { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt index b23ce947d..2821a6648 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt @@ -67,7 +67,8 @@ public interface AlgebraND> { * @return a feature object or `null` if it isn't present. */ @UnstableKMathAPI - public fun getFeature(structure: StructureND, type: KClass): F? = structure.getFeature(type) + public fun getFeature(structure: StructureND, type: KClass): F? = + structure.getFeature(type) public companion object } @@ -81,7 +82,7 @@ public interface AlgebraND> { * @return a feature object or `null` if it isn't present. */ @UnstableKMathAPI -public inline fun AlgebraND.getFeature(structure: StructureND): F? = +public inline fun AlgebraND.getFeature(structure: StructureND): F? = getFeature(structure, F::class) /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 8cf5d18cb..5483ed28f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -15,6 +15,8 @@ public interface Structure1D : StructureND, Buffer { } public override operator fun iterator(): Iterator = (0 until size).asSequence().map(::get).iterator() + + public companion object } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 3834cd97c..5dfdd028a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -69,7 +69,7 @@ private inline class Structure2DWrapper(val structure: StructureND) : Stru override operator fun get(i: Int, j: Int): T = structure[i, j] @UnstableKMathAPI - override fun getFeature(type: KClass): F? = structure.getFeature(type) + override fun getFeature(type: KClass): F? = structure.getFeature(type) override fun elements(): Sequence> = structure.elements() } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index 78eac1809..a1aa5e554 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -7,6 +7,8 @@ import kotlin.jvm.JvmName import kotlin.native.concurrent.ThreadLocal import kotlin.reflect.KClass +public interface StructureFeature + /** * Represents n-dimensional structure, i.e. multidimensional container of items of the same type and size. The number * of dimensions and items in an array is defined by its shape, which is a sequence of non-negative integers that @@ -48,7 +50,7 @@ public interface StructureND { * If the feature is not present, null is returned. */ @UnstableKMathAPI - public fun getFeature(type: KClass): F? = null + public fun getFeature(type: KClass): F? = null public companion object { /** @@ -144,7 +146,7 @@ public interface StructureND { public operator fun StructureND.get(vararg index: Int): T = get(index) @UnstableKMathAPI -public inline fun StructureND<*>.getFeature(): T? = getFeature(T::class) +public inline fun StructureND<*>.getFeature(): T? = getFeature(T::class) /** * Represents mutable [StructureND]. diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt index bc4508994..ba6adf35b 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt @@ -8,5 +8,5 @@ public abstract class BlockingDoubleChain : Chain { override suspend fun next(): Double = nextDouble() - public fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { nextDouble() } + public open fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { nextDouble() } } diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index a82fe933e..f84a57c9d 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -4,6 +4,7 @@ import org.ejml.dense.row.factory.DecompositionFactory_DDRM import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.nd.getFeature import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.DoubleBuffer @@ -89,7 +90,7 @@ public object EjmlLinearSpace : LinearSpace { v.toEjml().origin.scale(this).wrapVector() @UnstableKMathAPI - override fun getFeature(structure: Matrix, type: KClass): F? { + override fun getFeature(structure: Matrix, type: KClass): F? { //Return the feature if it is intrinsic to the structure structure.getFeature(type)?.let { return it } diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt index 35297a3ac..446a3d9cb 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt @@ -1,7 +1,43 @@ package space.kscience.kmath.real -import space.kscience.kmath.structures.asBuffer -import kotlin.math.abs +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.DoubleBuffer +import kotlin.math.floor + +public val ClosedFloatingPointRange.length: Double get() = endInclusive - start + +/** + * Create a Buffer-based grid with equally distributed [numberOfPoints] points. The range could be increasing or decreasing. + * If range has a zero size, then the buffer consisting of [numberOfPoints] equal values is returned. + */ +@UnstableKMathAPI +public fun Buffer.Companion.fromRange(range: ClosedFloatingPointRange, numberOfPoints: Int): DoubleBuffer { + require(numberOfPoints >= 2) { "Number of points in grid must be more than 1" } + val normalizedRange = when { + range.endInclusive > range.start -> range + range.endInclusive < range.start -> range.endInclusive..range.start + else -> return DoubleBuffer(numberOfPoints) { range.start } + } + val step = normalizedRange.length / (numberOfPoints - 1) + return DoubleBuffer(numberOfPoints) { normalizedRange.start + step * it / (numberOfPoints - 1) } +} + +/** + * Create a Buffer-based grid with equally distributed points with a fixed [step]. The range could be increasing or decreasing. + * If the step is larger than the range size, single point is returned. + */ +@UnstableKMathAPI +public fun Buffer.Companion.fromRange(range: ClosedFloatingPointRange, step: Double): DoubleBuffer { + require(step > 0) { "The grid step must be positive" } + val normalizedRange = when { + range.endInclusive > range.start -> range + range.endInclusive < range.start -> range.endInclusive..range.start + else -> return DoubleBuffer(range.start) + } + val numberOfPoints = floor(normalizedRange.length / step).toInt() + return DoubleBuffer(numberOfPoints) { normalizedRange.start + step * it / (numberOfPoints - 1) } +} /** * Convert double range to sequence. @@ -11,35 +47,5 @@ import kotlin.math.abs * * If step is negative, the same goes from upper boundary downwards */ -public fun ClosedFloatingPointRange.toSequenceWithStep(step: Double): Sequence = when { - step == 0.0 -> error("Zero step in double progression") - - step > 0 -> sequence { - var current = start - - while (current <= endInclusive) { - yield(current) - current += step - } - } - - else -> sequence { - var current = endInclusive - - while (current >= start) { - yield(current) - current += step - } - } -} - -public infix fun ClosedFloatingPointRange.step(step: Double): DoubleVector = - toSequenceWithStep(step).toList().asBuffer() - -/** - * Convert double range to sequence with the fixed number of points - */ -public fun ClosedFloatingPointRange.toSequenceWithPoints(numPoints: Int): Sequence { - require(numPoints > 1) { "The number of points should be more than 2" } - return toSequenceWithStep(abs(endInclusive - start) / (numPoints - 1)) -} +@UnstableKMathAPI +public infix fun ClosedFloatingPointRange.step(step: Double): DoubleBuffer = Buffer.fromRange(this, step) \ No newline at end of file diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index 5b29a9e64..bc3890b1e 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -3,14 +3,6 @@ plugins { } kotlin.sourceSets { - all { - languageSettings.apply { - useExperimentalAnnotation("kotlinx.coroutines.FlowPreview") - useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi") - useExperimentalAnnotation("kotlinx.coroutines.ObsoleteCoroutinesApi") - } - } - commonMain { dependencies { api(project(":kmath-coroutines")) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/DataFit.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/DataFit.kt new file mode 100644 index 000000000..e9a5dea86 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/DataFit.kt @@ -0,0 +1,17 @@ +package space.kscience.kmath.optimization + +import space.kscience.kmath.expressions.DifferentiableExpression +import space.kscience.kmath.expressions.StringSymbol +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.structures.Buffer + +public interface DataFit : Optimization { + + public fun modelAndData( + x: Buffer, + y: Buffer, + yErr: Buffer, + model: DifferentiableExpression, + xSymbol: Symbol = StringSymbol("x"), + ) +} \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt new file mode 100644 index 000000000..bf37f5c64 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt @@ -0,0 +1,122 @@ +package space.kscience.kmath.optimization + +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.indices +import kotlin.math.pow + +/** + * A likelihood function optimization problem + */ +public interface FunctionOptimization: Optimization, DataFit { + /** + * Define the initial guess for the optimization problem + */ + public fun initialGuess(map: Map) + + /** + * Set an objective function expression + */ + public fun expression(expression: Expression) + + /** + * Set a differentiable expression as objective function as function and gradient provider + */ + public fun diffExpression(expression: DifferentiableExpression>) + + override fun modelAndData( + x: Buffer, + y: Buffer, + yErr: Buffer, + model: DifferentiableExpression, + xSymbol: Symbol, + ) { + require(x.size == y.size) { "X and y buffers should be of the same size" } + require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } + + } + + public companion object{ + /** + * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation + */ + public fun chiSquared( + autoDiff: AutoDiffProcessor>, + x: Buffer, + y: Buffer, + yErr: Buffer, + model: A.(I) -> I, + ): DifferentiableExpression> where A : ExtendedField, A : ExpressionAlgebra { + require(x.size == y.size) { "X and y buffers should be of the same size" } + require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } + + return autoDiff.process { + var sum = zero + + x.indices.forEach { + val xValue = const(x[it]) + val yValue = const(y[it]) + val yErrValue = const(yErr[it]) + val modelValue = model(xValue) + sum += ((yValue - modelValue) / yErrValue).pow(2) + } + + sum + } + } + + /** + * Generate a chi squared expression from given x-y-sigma model represented by an expression. Does not provide derivatives + */ + public fun chiSquared( + x: Buffer, + y: Buffer, + yErr: Buffer, + model: Expression, + xSymbol: Symbol = StringSymbol("x"), + ): Expression { + require(x.size == y.size) { "X and y buffers should be of the same size" } + require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } + + return Expression { arguments -> + x.indices.sumByDouble { + val xValue = x[it] + val yValue = y[it] + val yErrValue = yErr[it] + val modifiedArgs = arguments + (xSymbol to xValue) + val modelValue = model(modifiedArgs) + ((yValue - modelValue) / yErrValue).pow(2) + } + } + } + } +} + +/** + * Optimize expression without derivatives using specific [OptimizationProblemFactory] + */ +public fun > Expression.optimizeWith( + factory: OptimizationProblemFactory, + vararg symbols: Symbol, + configuration: F.() -> Unit, +): OptimizationResult { + require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } + val problem = factory(symbols.toList(), configuration) + problem.expression(this) + return problem.optimize() +} + +/** + * Optimize differentiable expression using specific [OptimizationProblemFactory] + */ +public fun > DifferentiableExpression>.optimizeWith( + factory: OptimizationProblemFactory, + vararg symbols: Symbol, + configuration: F.() -> Unit, +): OptimizationResult { + require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } + val problem = factory(symbols.toList(), configuration) + problem.diffExpression(this) + return problem.optimize() +} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt new file mode 100644 index 000000000..370274b41 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt @@ -0,0 +1,44 @@ +package space.kscience.kmath.optimization + +import space.kscience.kmath.expressions.Symbol + +public interface OptimizationFeature + +public class OptimizationResult( + public val point: Map, + public val value: T, + public val features: Set = emptySet(), +) { + override fun toString(): String { + return "OptimizationResult(point=$point, value=$value)" + } +} + +public operator fun OptimizationResult.plus( + feature: OptimizationFeature, +): OptimizationResult = OptimizationResult(point, value, features + feature) + +/** + * An optimization problem builder over [T] variables + */ +public interface Optimization { + + /** + * Update the problem from previous optimization run + */ + public fun update(result: OptimizationResult) + + /** + * Make an optimization run + */ + public fun optimize(): OptimizationResult +} + +public fun interface OptimizationProblemFactory> { + public fun build(symbols: List): P +} + +public operator fun > OptimizationProblemFactory.invoke( + symbols: List, + block: P.() -> Unit, +): P = build(symbols).apply(block) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Fitting.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Fitting.kt deleted file mode 100644 index b006c8ba2..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Fitting.kt +++ /dev/null @@ -1,63 +0,0 @@ -package space.kscience.kmath.stat - -import space.kscience.kmath.expressions.* -import space.kscience.kmath.operations.ExtendedField -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.indices -import kotlin.math.pow - -public object Fitting { - - /** - * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation - */ - public fun chiSquared( - autoDiff: AutoDiffProcessor>, - x: Buffer, - y: Buffer, - yErr: Buffer, - model: A.(I) -> I, - ): DifferentiableExpression> where A : ExtendedField, A : ExpressionAlgebra { - require(x.size == y.size) { "X and y buffers should be of the same size" } - require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } - - return autoDiff.process { - var sum = zero - - x.indices.forEach { - val xValue = const(x[it]) - val yValue = const(y[it]) - val yErrValue = const(yErr[it]) - val modelValue = model(xValue) - sum += ((yValue - modelValue) / yErrValue).pow(2) - } - - sum - } - } - - /** - * Generate a chi squared expression from given x-y-sigma model represented by an expression. Does not provide derivatives - */ - public fun chiSquared( - x: Buffer, - y: Buffer, - yErr: Buffer, - model: Expression, - xSymbol: Symbol = StringSymbol("x"), - ): Expression { - require(x.size == y.size) { "X and y buffers should be of the same size" } - require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } - - return Expression { arguments -> - x.indices.sumByDouble { - val xValue = x[it] - val yValue = y[it] - val yErrValue = yErr[it] - val modifiedArgs = arguments + (xSymbol to xValue) - val modelValue = model(modifiedArgs) - ((yValue - modelValue) / yErrValue).pow(2) - } - } - } -} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt deleted file mode 100644 index ffa24fa98..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt +++ /dev/null @@ -1,88 +0,0 @@ -package space.kscience.kmath.stat - -import space.kscience.kmath.expressions.DifferentiableExpression -import space.kscience.kmath.expressions.Expression -import space.kscience.kmath.expressions.Symbol - -public interface OptimizationFeature - -public class OptimizationResult( - public val point: Map, - public val value: T, - public val features: Set = emptySet(), -) { - override fun toString(): String { - return "OptimizationResult(point=$point, value=$value)" - } -} - -public operator fun OptimizationResult.plus( - feature: OptimizationFeature, -): OptimizationResult = OptimizationResult(point, value, features + feature) - -/** - * A configuration builder for optimization problem - */ -public interface OptimizationProblem { - /** - * Define the initial guess for the optimization problem - */ - public fun initialGuess(map: Map) - - /** - * Set an objective function expression - */ - public fun expression(expression: Expression) - - /** - * Set a differentiable expression as objective function as function and gradient provider - */ - public fun diffExpression(expression: DifferentiableExpression>) - - /** - * Update the problem from previous optimization run - */ - public fun update(result: OptimizationResult) - - /** - * Make an optimization run - */ - public fun optimize(): OptimizationResult -} - -public fun interface OptimizationProblemFactory> { - public fun build(symbols: List): P -} - -public operator fun > OptimizationProblemFactory.invoke( - symbols: List, - block: P.() -> Unit, -): P = build(symbols).apply(block) - -/** - * Optimize expression without derivatives using specific [OptimizationProblemFactory] - */ -public fun > Expression.optimizeWith( - factory: OptimizationProblemFactory, - vararg symbols: Symbol, - configuration: F.() -> Unit, -): OptimizationResult { - require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = factory(symbols.toList(), configuration) - problem.expression(this) - return problem.optimize() -} - -/** - * Optimize differentiable expression using specific [OptimizationProblemFactory] - */ -public fun > DifferentiableExpression>.optimizeWith( - factory: OptimizationProblemFactory, - vararg symbols: Symbol, - configuration: F.() -> Unit, -): OptimizationResult { - require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = factory(symbols.toList(), configuration) - problem.diffExpression(this) - return problem.optimize() -} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt index 6e1f36c8a..978094ffd 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt @@ -14,4 +14,4 @@ public class RandomChain( override fun fork(): Chain = RandomChain(generator.fork(), gen) } -public fun RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain = RandomChain(this, gen) +public fun RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain = RandomChain(this, gen) \ No newline at end of file diff --git a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt index 8b5551a16..c3d711789 100644 --- a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt +++ b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt @@ -80,19 +80,20 @@ public fun Distribution.Companion.normal( override fun probability(arg: Double): Double = exp(-(arg - mean).pow(2) / 2 / sigma2) / norm } -public fun Distribution.Companion.poisson(lambda: Double): DiscreteSamplerDistribution = - object : DiscreteSamplerDistribution() { - private val computedProb: MutableMap = hashMapOf(0 to exp(-lambda)) +public fun Distribution.Companion.poisson( + lambda: Double, +): DiscreteSamplerDistribution = object : DiscreteSamplerDistribution() { + private val computedProb: HashMap = hashMapOf(0 to exp(-lambda)) - override fun buildSampler(generator: RandomGenerator): DiscreteSampler = - PoissonSampler.of(generator.asUniformRandomProvider(), lambda) + override fun buildSampler(generator: RandomGenerator): DiscreteSampler = + PoissonSampler.of(generator.asUniformRandomProvider(), lambda) - override fun probability(arg: Int): Double { - require(arg >= 0) { "The argument must be >= 0" } + override fun probability(arg: Int): Double { + require(arg >= 0) { "The argument must be >= 0" } - return if (arg > 40) - exp(-(arg - lambda).pow(2) / 2 / lambda) / sqrt(2 * PI * lambda) - else - computedProb.getOrPut(arg) { probability(arg - 1) * lambda / arg } - } + return if (arg > 40) + exp(-(arg - lambda).pow(2) / 2 / lambda) / sqrt(2 * PI * lambda) + else + computedProb.getOrPut(arg) { probability(arg - 1) * lambda / arg } } +} From aeceb4a3371576565581c2f0b7a181a320c8894b Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 19 Mar 2021 14:53:14 +0300 Subject: [PATCH 112/393] Move dataset to core --- CHANGELOG.md | 1 + .../ExpressionsInterpretersBenchmark.kt | 2 +- .../kscience/kmath/ast/kotlingradSupport.kt | 2 +- .../kmath/commons/fit/fitWithAutoDiff.kt | 2 +- .../space/kscience/kmath/ast/MstExpression.kt | 2 + .../kmath/estree/internal/ESTreeBuilder.kt | 2 +- .../kmath/asm/internal/mapIntrinsics.kt | 4 +- .../DerivativeStructureExpression.kt | 2 + .../commons/optimization/CMOptimization.kt | 8 +- .../kmath/commons/optimization/cmFit.kt | 2 +- .../DerivativeStructureExpressionTest.kt | 6 +- .../commons/optimization/OptimizeTest.kt | 2 +- .../complex/ExpressionFieldForComplexTest.kt | 2 +- kmath-core/api/kmath-core.api | 155 ++++++++---------- .../expressions/DifferentiableExpression.kt | 3 + .../kscience/kmath/expressions/Expression.kt | 26 +-- .../FunctionalExpressionAlgebra.kt | 1 + .../kmath/expressions/SimpleAutoDiff.kt | 1 + .../kmath/expressions/SymbolIndexer.kt | 6 + .../space/kscience/kmath/misc/ColumnarData.kt | 15 ++ .../space/kscience/kmath/misc/Symbol.kt | 34 ++++ .../space/kscience/kmath/misc}/XYPointSet.kt | 39 +++-- .../kscience/kmath/operations/Algebra.kt | 2 +- .../kmath/structures/bufferOperation.kt | 9 + .../kmath/expressions/ExpressionFieldTest.kt | 1 + .../kmath/expressions/SimpleAutoDiffTest.kt | 2 + .../space/kscience/kmath/real/RealVector.kt | 14 +- .../kotlin/space/kscience/kmath/real/grids.kt | 12 +- .../kotlin/kaceince/kmath/real/GridTest.kt | 5 + .../kmath/interpolation/Interpolator.kt | 15 +- .../kmath/interpolation/LinearInterpolator.kt | 11 +- .../kmath/interpolation/SplineInterpolator.kt | 5 +- .../kotlingrad/DifferentiableMstExpression.kt | 2 +- .../kscience/kmath/optimization/DataFit.kt | 4 +- .../optimization/FunctionOptimization.kt | 7 +- .../kmath/optimization/Optimization.kt | 2 +- 36 files changed, 246 insertions(+), 162 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/ColumnarData.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt rename {kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation => kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc}/XYPointSet.kt (57%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b4dddf81..4ade9cd9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Buffer factories for primitives moved to MutableBuffer.Companion - NDStructure and NDAlgebra to StructureND and AlgebraND respectively - Real -> Double +- DataSets are moved from functions to core ### Deprecated diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index 0899241f9..2438e3979 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.ast.mstInField import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.expressionInField import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol import kotlin.random.Random diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt index 23c9d5b41..138b3e708 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt @@ -3,8 +3,8 @@ package space.kscience.kmath.ast import space.kscience.kmath.asm.compile import space.kscience.kmath.expressions.derivative import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.expressions.symbol import space.kscience.kmath.kotlingrad.differentiable +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField /** diff --git a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt index 6141a1058..ca4d9c181 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -7,7 +7,7 @@ import kscience.plotly.models.ScatterMode import kscience.plotly.models.TraceValues import space.kscience.kmath.commons.optimization.chiSquared import space.kscience.kmath.commons.optimization.minimize -import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.misc.symbol import space.kscience.kmath.optimization.FunctionOptimization import space.kscience.kmath.optimization.OptimizationResult import space.kscience.kmath.real.DoubleVector diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt index 63dfb38f7..5c43df068 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt @@ -1,6 +1,8 @@ package space.kscience.kmath.ast import space.kscience.kmath.expressions.* +import space.kscience.kmath.misc.StringSymbol +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.* import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt index b4de9968d..1e966d986 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -3,7 +3,7 @@ package space.kscience.kmath.estree.internal import space.kscience.kmath.estree.internal.astring.generate import space.kscience.kmath.estree.internal.estree.* import space.kscience.kmath.expressions.Expression -import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.misc.Symbol internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExpression) { private class GeneratedExpression(val executable: dynamic, val constants: Array) : Expression { diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt index f54bc070c..0a0c21d8a 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt @@ -2,8 +2,8 @@ package space.kscience.kmath.asm.internal -import space.kscience.kmath.expressions.StringSymbol -import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.misc.StringSymbol +import space.kscience.kmath.misc.Symbol /** * Gets value with given [key] or throws [NoSuchElementException] whenever it is not present. diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index b74167c3f..58e9687e5 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -2,6 +2,8 @@ package space.kscience.kmath.commons.expressions import org.apache.commons.math3.analysis.differentiation.DerivativeStructure import space.kscience.kmath.expressions.* +import space.kscience.kmath.misc.StringSymbol +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.NumbersAddOperations diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt index 6200b61a9..93d0f0bba 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt @@ -9,7 +9,12 @@ import org.apache.commons.math3.optim.nonlinear.scalar.gradient.NonLinearConjuga import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.AbstractSimplex import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer -import space.kscience.kmath.expressions.* +import space.kscience.kmath.expressions.DifferentiableExpression +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.SymbolIndexer +import space.kscience.kmath.expressions.derivative +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.optimization.FunctionOptimization import space.kscience.kmath.optimization.OptimizationFeature import space.kscience.kmath.optimization.OptimizationProblemFactory @@ -19,6 +24,7 @@ import kotlin.reflect.KClass public operator fun PointValuePair.component1(): DoubleArray = point public operator fun PointValuePair.component2(): Double = value +@OptIn(UnstableKMathAPI::class) public class CMOptimization( override val symbols: List, ) : FunctionOptimization, SymbolIndexer, OptimizationFeature { diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt index 384414e6d..8e9ce7a80 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt @@ -5,7 +5,7 @@ import org.apache.commons.math3.optim.nonlinear.scalar.GoalType import space.kscience.kmath.commons.expressions.DerivativeStructureField import space.kscience.kmath.expressions.DifferentiableExpression import space.kscience.kmath.expressions.Expression -import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.optimization.FunctionOptimization import space.kscience.kmath.optimization.OptimizationResult import space.kscience.kmath.optimization.optimizeWith diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt index 8d9bab652..b19eb5950 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt @@ -1,6 +1,10 @@ package space.kscience.kmath.commons.expressions -import space.kscience.kmath.expressions.* +import space.kscience.kmath.expressions.binding +import space.kscience.kmath.expressions.derivative +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.symbol import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.test.Test diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt index cbbe1457e..5f5d3e1e4 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.commons.optimization import org.junit.jupiter.api.Test import space.kscience.kmath.commons.expressions.DerivativeStructureExpression -import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.misc.symbol import space.kscience.kmath.optimization.FunctionOptimization import space.kscience.kmath.stat.Distribution import space.kscience.kmath.stat.RandomGenerator diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt index 81a131318..3837b0d40 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt @@ -3,7 +3,7 @@ package space.kscience.kmath.complex import space.kscience.kmath.expressions.FunctionalExpressionField import space.kscience.kmath.expressions.bindSymbol import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.misc.symbol import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 8c62198cd..570e50a86 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -14,7 +14,7 @@ public class space/kscience/kmath/expressions/AutoDiffValue { public final class space/kscience/kmath/expressions/DerivationResult { public fun (Ljava/lang/Object;Ljava/util/Map;Lspace/kscience/kmath/operations/Field;)V - public final fun derivative (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public final fun derivative (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; public final fun div ()Ljava/lang/Object; public final fun getContext ()Lspace/kscience/kmath/operations/Field; public final fun getValue ()Ljava/lang/Object; @@ -27,7 +27,7 @@ public abstract interface class space/kscience/kmath/expressions/DifferentiableE public final class space/kscience/kmath/expressions/DifferentiableExpressionKt { public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression; public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; - public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;[Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression; + public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;[Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression; } public abstract interface class space/kscience/kmath/expressions/Expression { @@ -36,7 +36,7 @@ public abstract interface class space/kscience/kmath/expressions/Expression { public abstract interface class space/kscience/kmath/expressions/ExpressionAlgebra : space/kscience/kmath/operations/Algebra { public abstract fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public abstract fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public abstract fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; public abstract fun const (Ljava/lang/Object;)Ljava/lang/Object; } @@ -56,18 +56,17 @@ public final class space/kscience/kmath/expressions/ExpressionBuildersKt { } public final class space/kscience/kmath/expressions/ExpressionKt { - public static final fun bindSymbol (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public static final fun bindSymbol (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; public static final fun binding (Lspace/kscience/kmath/expressions/ExpressionAlgebra;)Lkotlin/properties/ReadOnlyProperty; public static final fun callByString (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object; public static final fun callBySymbol (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object; - public static final fun getSymbol ()Lkotlin/properties/ReadOnlyProperty; public static final fun invoke (Lspace/kscience/kmath/expressions/Expression;)Ljava/lang/Object; } public abstract class space/kscience/kmath/expressions/FirstDerivativeExpression : space/kscience/kmath/expressions/DifferentiableExpression { public fun ()V public final fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; - public abstract fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression; + public abstract fun derivativeOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression; } public abstract class space/kscience/kmath/expressions/FunctionalExpressionAlgebra : space/kscience/kmath/expressions/ExpressionAlgebra { @@ -77,8 +76,8 @@ public abstract class space/kscience/kmath/expressions/FunctionalExpressionAlgeb public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression; + public synthetic fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; + public fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun const (Ljava/lang/Object;)Ljava/lang/Object; public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression; public final fun getAlgebra ()Lspace/kscience/kmath/operations/Algebra; @@ -203,7 +202,7 @@ public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/k public final class space/kscience/kmath/expressions/SimpleAutoDiffExpression : space/kscience/kmath/expressions/FirstDerivativeExpression { public fun (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)V - public fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression; + public fun derivativeOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression; public final fun getField ()Lspace/kscience/kmath/operations/Field; public final fun getFunction ()Lkotlin/jvm/functions/Function1; public fun invoke (Ljava/util/Map;)Ljava/lang/Object; @@ -264,8 +263,8 @@ public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscien public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public synthetic fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/AutoDiffValue; + public synthetic fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; + public fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun const (Ljava/lang/Object;)Ljava/lang/Object; public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/AutoDiffValue; public final fun const (Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/AutoDiffValue; @@ -332,7 +331,7 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt { public static final fun cos (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public static final fun cosh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public static final fun exp (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public static final fun grad (Lspace/kscience/kmath/expressions/DerivationResult;[Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer; + public static final fun grad (Lspace/kscience/kmath/expressions/DerivationResult;[Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer; public static final fun ln (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public static final fun pow (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;D)Lspace/kscience/kmath/expressions/AutoDiffValue; public static final fun pow (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;I)Lspace/kscience/kmath/expressions/AutoDiffValue; @@ -348,79 +347,13 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt { public static final fun tanh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; } -public final class space/kscience/kmath/expressions/SimpleSymbolIndexer : space/kscience/kmath/expressions/SymbolIndexer { - public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/expressions/SimpleSymbolIndexer; - public static fun constructor-impl (Ljava/util/List;)Ljava/util/List; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Ljava/util/List;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Ljava/util/List;Ljava/util/List;)Z - public fun get (Ljava/util/List;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public fun get (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public fun get (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public fun get ([DLspace/kscience/kmath/expressions/Symbol;)D - public fun get ([Ljava/lang/Object;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public static fun get-impl (Ljava/util/List;Ljava/util/List;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public static fun get-impl (Ljava/util/List;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public static fun get-impl (Ljava/util/List;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public static fun get-impl (Ljava/util/List;[DLspace/kscience/kmath/expressions/Symbol;)D - public static fun get-impl (Ljava/util/List;[Ljava/lang/Object;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public fun getSymbols ()Ljava/util/List; - public fun hashCode ()I - public static fun hashCode-impl (Ljava/util/List;)I - public fun indexOf (Lspace/kscience/kmath/expressions/Symbol;)I - public static fun indexOf-impl (Ljava/util/List;Lspace/kscience/kmath/expressions/Symbol;)I - public fun toDoubleArray (Ljava/util/Map;)[D - public static fun toDoubleArray-impl (Ljava/util/List;Ljava/util/Map;)[D - public fun toList (Ljava/util/Map;)Ljava/util/List; - public static fun toList-impl (Ljava/util/List;Ljava/util/Map;)Ljava/util/List; - public fun toMap ([D)Ljava/util/Map; - public static fun toMap-impl (Ljava/util/List;[D)Ljava/util/Map; - public fun toPoint (Ljava/util/Map;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; - public static fun toPoint-impl (Ljava/util/List;Ljava/util/Map;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Ljava/util/List;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Ljava/util/List; -} - -public final class space/kscience/kmath/expressions/StringSymbol : space/kscience/kmath/expressions/Symbol { - public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/expressions/StringSymbol; - public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z - public fun getIdentity ()Ljava/lang/String; - public fun hashCode ()I - public static fun hashCode-impl (Ljava/lang/String;)I - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Ljava/lang/String; -} - -public abstract interface class space/kscience/kmath/expressions/Symbol { - public abstract fun getIdentity ()Ljava/lang/String; -} - -public abstract interface class space/kscience/kmath/expressions/SymbolIndexer { - public abstract fun get (Ljava/util/List;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public abstract fun get (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public abstract fun get (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public abstract fun get ([DLspace/kscience/kmath/expressions/Symbol;)D - public abstract fun get ([Ljava/lang/Object;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public abstract fun getSymbols ()Ljava/util/List; - public abstract fun indexOf (Lspace/kscience/kmath/expressions/Symbol;)I - public abstract fun toDoubleArray (Ljava/util/Map;)[D - public abstract fun toList (Ljava/util/Map;)Ljava/util/List; - public abstract fun toMap ([D)Ljava/util/Map; - public abstract fun toPoint (Ljava/util/Map;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; -} - public final class space/kscience/kmath/expressions/SymbolIndexer$DefaultImpls { - public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/List;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;[DLspace/kscience/kmath/expressions/Symbol;)D - public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;[Ljava/lang/Object;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public static fun indexOf (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/expressions/Symbol;)I + public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/List;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; + public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/misc/Symbol;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; + public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; + public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;[DLspace/kscience/kmath/misc/Symbol;)D + public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;[Ljava/lang/Object;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; + public static fun indexOf (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/misc/Symbol;)I public static fun toDoubleArray (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/Map;)[D public static fun toList (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/Map;)Ljava/util/List; public static fun toMap (Lspace/kscience/kmath/expressions/SymbolIndexer;[D)Ljava/util/Map; @@ -428,8 +361,6 @@ public final class space/kscience/kmath/expressions/SymbolIndexer$DefaultImpls { } public final class space/kscience/kmath/expressions/SymbolIndexerKt { - public static final fun withSymbols (Ljava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun withSymbols ([Lspace/kscience/kmath/expressions/Symbol;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } public final class space/kscience/kmath/linear/BufferedLinearSpace : space/kscience/kmath/linear/LinearSpace { @@ -672,9 +603,58 @@ public final class space/kscience/kmath/misc/CumulativeKt { public static final fun cumulativeSumOfLong (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; } +public final class space/kscience/kmath/misc/NDStructureColumn : space/kscience/kmath/structures/Buffer { + public fun (Lspace/kscience/kmath/nd/Structure2D;I)V + public fun get (I)Ljava/lang/Object; + public final fun getColumn ()I + public fun getSize ()I + public final fun getStructure ()Lspace/kscience/kmath/nd/Structure2D; + public fun iterator ()Ljava/util/Iterator; +} + +public final class space/kscience/kmath/misc/StringSymbol : space/kscience/kmath/misc/Symbol { + public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/misc/StringSymbol; + public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z + public fun getIdentity ()Ljava/lang/String; + public fun hashCode ()I + public static fun hashCode-impl (Ljava/lang/String;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Ljava/lang/String; +} + +public abstract interface class space/kscience/kmath/misc/Symbol { + public static final field Companion Lspace/kscience/kmath/misc/Symbol$Companion; + public abstract fun getIdentity ()Ljava/lang/String; +} + +public final class space/kscience/kmath/misc/Symbol$Companion { + public final fun getX-tWtZOCg ()Ljava/lang/String; + public final fun getY-tWtZOCg ()Ljava/lang/String; + public final fun getZ-tWtZOCg ()Ljava/lang/String; +} + +public final class space/kscience/kmath/misc/SymbolKt { + public static final fun getSymbol ()Lkotlin/properties/ReadOnlyProperty; +} + public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation { } +public final class space/kscience/kmath/misc/XYPointSet$DefaultImpls { + public static fun get (Lspace/kscience/kmath/misc/XYPointSet;Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer; +} + +public final class space/kscience/kmath/misc/XYPointSetKt { +} + +public final class space/kscience/kmath/misc/XYZPointSet$DefaultImpls { + public static fun get (Lspace/kscience/kmath/misc/XYZPointSet;Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer; +} + public abstract interface class space/kscience/kmath/nd/AlgebraND { public static final field Companion Lspace/kscience/kmath/nd/AlgebraND$Companion; public abstract fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; @@ -1180,7 +1160,7 @@ public final class space/kscience/kmath/operations/AlgebraExtensionsKt { } public final class space/kscience/kmath/operations/AlgebraKt { - public static final fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public static final fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; public static final fun invoke (Lspace/kscience/kmath/operations/Algebra;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } @@ -2119,6 +2099,7 @@ public final class space/kscience/kmath/structures/BufferKt { public final class space/kscience/kmath/structures/BufferOperationKt { public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable; public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence; + public static final fun fold (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; public static final fun toList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List; } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt index 5cbc4dbf4..1f0ceaec3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt @@ -1,5 +1,8 @@ package space.kscience.kmath.expressions +import space.kscience.kmath.misc.StringSymbol +import space.kscience.kmath.misc.Symbol + /** * Represents expression which structure can be differentiated. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt index 5ba24aa62..7918f199e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt @@ -1,26 +1,11 @@ package space.kscience.kmath.expressions +import space.kscience.kmath.misc.StringSymbol +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra import kotlin.jvm.JvmName import kotlin.properties.ReadOnlyProperty -/** - * A marker interface for a symbol. A symbol mus have an identity - */ -public interface Symbol { - /** - * Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol. - */ - public val identity: String -} - -/** - * A [Symbol] with a [String] identity - */ -public inline class StringSymbol(override val identity: String) : Symbol { - override fun toString(): String = identity -} - /** * An elementary function that could be invoked on a map of arguments. * @@ -92,13 +77,6 @@ public interface ExpressionAlgebra : Algebra { public fun ExpressionAlgebra.bindSymbol(symbol: Symbol): E = bindSymbolOrNull(symbol) ?: error("Symbol $symbol could not be bound to $this") -/** - * A delegate to create a symbol with a string identity in this scope - */ -public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> - StringSymbol(property.name) -} - /** * Bind a symbol by name inside the [ExpressionAlgebra] */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index cca75754f..ebd9e7f22 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.expressions +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.* /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt index 4b0d402ed..d9be4a92e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.expressions import space.kscience.kmath.linear.Point +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import space.kscience.kmath.structures.asBuffer diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt index 580acaafb..4db4b5828 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt @@ -1,6 +1,8 @@ package space.kscience.kmath.expressions import space.kscience.kmath.linear.Point +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.structures.BufferFactory @@ -8,6 +10,7 @@ import space.kscience.kmath.structures.BufferFactory * An environment to easy transform indexed variables to symbols and back. * TODO requires multi-receivers to be beautiful */ +@UnstableKMathAPI public interface SymbolIndexer { public val symbols: List public fun indexOf(symbol: Symbol): Int = symbols.indexOf(symbol) @@ -49,13 +52,16 @@ public interface SymbolIndexer { public fun Map.toDoubleArray(): DoubleArray = DoubleArray(symbols.size) { getValue(symbols[it]) } } +@UnstableKMathAPI public inline class SimpleSymbolIndexer(override val symbols: List) : SymbolIndexer /** * Execute the block with symbol indexer based on given symbol order */ +@UnstableKMathAPI public inline fun withSymbols(vararg symbols: Symbol, block: SymbolIndexer.() -> R): R = with(SimpleSymbolIndexer(symbols.toList()), block) +@UnstableKMathAPI public inline fun withSymbols(symbols: Collection, block: SymbolIndexer.() -> R): R = with(SimpleSymbolIndexer(symbols.toList()), block) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/ColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/ColumnarData.kt new file mode 100644 index 000000000..ed5a7e8f0 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/ColumnarData.kt @@ -0,0 +1,15 @@ +package space.kscience.kmath.misc + +import space.kscience.kmath.structures.Buffer + +/** + * A column-based data set with all columns of the same size (not necessary fixed in time). + * The column could be retrieved by a [get] operation. + */ +@UnstableKMathAPI +public interface ColumnarData { + public val size: Int + + public operator fun get(symbol: Symbol): Buffer +} + diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt new file mode 100644 index 000000000..2c9774b6a --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt @@ -0,0 +1,34 @@ +package space.kscience.kmath.misc + +import kotlin.properties.ReadOnlyProperty + +/** + * A marker interface for a symbol. A symbol mus have an identity + */ +public interface Symbol { + /** + * Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol. + */ + public val identity: String + + public companion object{ + public val x: StringSymbol = StringSymbol("x") + public val y: StringSymbol = StringSymbol("y") + public val z: StringSymbol = StringSymbol("z") + } +} + +/** + * A [Symbol] with a [String] identity + */ +public inline class StringSymbol(override val identity: String) : Symbol { + override fun toString(): String = identity +} + + +/** + * A delegate to create a symbol with a string identity in this scope + */ +public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> + StringSymbol(property.name) +} diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/XYPointSet.kt similarity index 57% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/XYPointSet.kt index 1ff7b6351..bc9052348 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/XYPointSet.kt @@ -1,22 +1,32 @@ -package space.kscience.kmath.interpolation +package space.kscience.kmath.misc import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.structures.Buffer -public interface XYPointSet { - public val size: Int +@UnstableKMathAPI +public interface XYPointSet : ColumnarData { public val x: Buffer public val y: Buffer + + override fun get(symbol: Symbol): Buffer = when (symbol) { + Symbol.x -> x + Symbol.y -> y + else -> error("A column for symbol $symbol not found") + } } -public interface XYZPointSet : XYPointSet { +@UnstableKMathAPI +public interface XYZPointSet : XYPointSet { public val z: Buffer + + override fun get(symbol: Symbol): Buffer = when (symbol) { + Symbol.x -> x + Symbol.y -> y + Symbol.z -> z + else -> error("A column for symbol $symbol not found") + } } -internal fun > insureSorted(points: XYPointSet) { - for (i in 0 until points.size - 1) - require(points.x[i + 1] > points.x[i]) { "Input data is not sorted at index $i" } -} public class NDStructureColumn(public val structure: Structure2D, public val column: Int) : Buffer { public override val size: Int @@ -30,22 +40,23 @@ public class NDStructureColumn(public val structure: Structure2D, public v public override operator fun iterator(): Iterator = sequence { repeat(size) { yield(get(it)) } }.iterator() } -public class BufferXYPointSet( +@UnstableKMathAPI +public class BufferXYPointSet( public override val x: Buffer, public override val y: Buffer, -) : XYPointSet { - public override val size: Int - get() = x.size +) : XYPointSet { + public override val size: Int get() = x.size init { require(x.size == y.size) { "Sizes of x and y buffers should be the same" } } } -public fun Structure2D.asXYPointSet(): XYPointSet { +@UnstableKMathAPI +public fun Structure2D.asXYPointSet(): XYPointSet { require(shape[1] == 2) { "Structure second dimension should be of size 2" } - return object : XYPointSet { + return object : XYPointSet { override val size: Int get() = this@asXYPointSet.shape[0] override val x: Buffer get() = NDStructureColumn(this@asXYPointSet, 0) override val y: Buffer get() = NDStructureColumn(this@asXYPointSet, 1) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 9f57bc4c1..04234205f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.operations -import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.misc.Symbol /** * Stub for DSL the [Algebra] is. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt index 4355ba17f..5f8bbe21f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt @@ -70,6 +70,15 @@ public inline fun Buffer.mapIndexed( crossinline block: (index: Int, value: T) -> R, ): Buffer = bufferFactory(size) { block(it, get(it)) } +/** + * Fold given buffer according to [operation] + */ +public inline fun Buffer.fold(initial: R, operation: (acc: R, T) -> R): R { + var accumulator = initial + for (index in this.indices) accumulator = operation(accumulator, get(index)) + return accumulator +} + /** * Zip two buffers using given [transform]. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt index b1be0c392..61b1d03f0 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.expressions +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke import kotlin.test.Test diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt index ca7aca905..666db13d8 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.expressions +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt index 433e3c756..6b059ef56 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt @@ -6,17 +6,13 @@ import space.kscience.kmath.operations.Norm import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MutableBuffer.Companion.double import space.kscience.kmath.structures.asBuffer -import space.kscience.kmath.structures.asIterable +import space.kscience.kmath.structures.fold import space.kscience.kmath.structures.indices import kotlin.math.pow import kotlin.math.sqrt public typealias DoubleVector = Point -public object VectorL2Norm : Norm, Double> { - override fun norm(arg: Point): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble)) -} - @Suppress("FunctionName") public fun DoubleVector(vararg doubles: Double): DoubleVector = doubles.asBuffer() @@ -102,4 +98,10 @@ public fun DoubleVector.sum(): Double { res += get(i) } return res -} \ No newline at end of file +} + +public object VectorL2Norm : Norm { + override fun norm(arg: DoubleVector): Double = sqrt(arg.fold(0.0) { acc: Double, d: Double -> acc + d.pow(2) }) +} + +public val DoubleVector.norm: Double get() = VectorL2Norm.norm(this) \ No newline at end of file diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt index 446a3d9cb..7f02c7db3 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt @@ -11,7 +11,6 @@ public val ClosedFloatingPointRange.length: Double get() = endInclusive * Create a Buffer-based grid with equally distributed [numberOfPoints] points. The range could be increasing or decreasing. * If range has a zero size, then the buffer consisting of [numberOfPoints] equal values is returned. */ -@UnstableKMathAPI public fun Buffer.Companion.fromRange(range: ClosedFloatingPointRange, numberOfPoints: Int): DoubleBuffer { require(numberOfPoints >= 2) { "Number of points in grid must be more than 1" } val normalizedRange = when { @@ -20,23 +19,22 @@ public fun Buffer.Companion.fromRange(range: ClosedFloatingPointRange, n else -> return DoubleBuffer(numberOfPoints) { range.start } } val step = normalizedRange.length / (numberOfPoints - 1) - return DoubleBuffer(numberOfPoints) { normalizedRange.start + step * it / (numberOfPoints - 1) } + return DoubleBuffer(numberOfPoints) { normalizedRange.start + step * it } } /** * Create a Buffer-based grid with equally distributed points with a fixed [step]. The range could be increasing or decreasing. * If the step is larger than the range size, single point is returned. */ -@UnstableKMathAPI -public fun Buffer.Companion.fromRange(range: ClosedFloatingPointRange, step: Double): DoubleBuffer { +public fun Buffer.Companion.withFixedStep(range: ClosedFloatingPointRange, step: Double): DoubleBuffer { require(step > 0) { "The grid step must be positive" } val normalizedRange = when { range.endInclusive > range.start -> range range.endInclusive < range.start -> range.endInclusive..range.start else -> return DoubleBuffer(range.start) } - val numberOfPoints = floor(normalizedRange.length / step).toInt() - return DoubleBuffer(numberOfPoints) { normalizedRange.start + step * it / (numberOfPoints - 1) } + val numberOfPoints = floor(normalizedRange.length / step).toInt() + 1 + return DoubleBuffer(numberOfPoints) { normalizedRange.start + step * it } } /** @@ -48,4 +46,4 @@ public fun Buffer.Companion.fromRange(range: ClosedFloatingPointRange, s * If step is negative, the same goes from upper boundary downwards */ @UnstableKMathAPI -public infix fun ClosedFloatingPointRange.step(step: Double): DoubleBuffer = Buffer.fromRange(this, step) \ No newline at end of file +public infix fun ClosedFloatingPointRange.step(step: Double): DoubleBuffer = Buffer.withFixedStep(this, step) \ No newline at end of file diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt index 5a644c8f9..91ee517ab 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt @@ -1,13 +1,18 @@ package kaceince.kmath.real +import space.kscience.kmath.real.DoubleVector +import space.kscience.kmath.real.minus +import space.kscience.kmath.real.norm import space.kscience.kmath.real.step import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertTrue class GridTest { @Test fun testStepGrid() { val grid = 0.0..1.0 step 0.2 assertEquals(6, grid.size) + assertTrue { (grid - DoubleVector(0.0, 0.2, 0.4, 0.6, 0.8, 1.0)).norm < 1e-4 } } } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt index fa978a9bc..864431d7a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -1,27 +1,32 @@ +@file:OptIn(UnstableKMathAPI::class) package space.kscience.kmath.interpolation import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.value +import space.kscience.kmath.misc.BufferXYPointSet +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.misc.XYPointSet import space.kscience.kmath.operations.Ring import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer -public fun interface Interpolator { - public fun interpolate(points: XYPointSet): (X) -> Y +public fun interface Interpolator { + public fun interpolate(points: XYPointSet): (X) -> Y } -public interface PolynomialInterpolator> : Interpolator { +public interface PolynomialInterpolator> : Interpolator { public val algebra: Ring public fun getDefaultValue(): T = error("Out of bounds") - public fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial + public fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial - override fun interpolate(points: XYPointSet): (T) -> T = { x -> + override fun interpolate(points: XYPointSet): (T) -> T = { x -> interpolatePolynomials(points).value(algebra, x) ?: getDefaultValue() } } + public fun > PolynomialInterpolator.interpolatePolynomials( x: Buffer, y: Buffer, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt index c939384e3..89a242ece 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt @@ -3,14 +3,23 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.functions.OrderedPiecewisePolynomial import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.Polynomial +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.misc.XYPointSet import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.invoke +@OptIn(UnstableKMathAPI::class) +internal fun > insureSorted(points: XYPointSet<*, T, *>) { + for (i in 0 until points.size - 1) + require(points.x[i + 1] > points.x[i]) { "Input data is not sorted at index $i" } +} + /** * Reference JVM implementation: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/analysis/interpolation/LinearInterpolator.java */ public class LinearInterpolator>(public override val algebra: Field) : PolynomialInterpolator { - public override fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial = algebra { + @OptIn(UnstableKMathAPI::class) + public override fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial = algebra { require(points.size > 0) { "Point array should not be empty" } insureSorted(points) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index ddbe743f0..8b6db8cf9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -3,6 +3,8 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.functions.OrderedPiecewisePolynomial import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.Polynomial +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.misc.XYPointSet import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.MutableBufferFactory @@ -17,7 +19,8 @@ public class SplineInterpolator>( ) : PolynomialInterpolator { //TODO possibly optimize zeroed buffers - public override fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial = algebra { + @OptIn(UnstableKMathAPI::class) + public override fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial = algebra { require(points.size >= 3) { "Can't use spline interpolator with less than 3 points" } insureSorted(points) // Number of intervals. The number of data points is n + 1. diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt index 39a7248b4..fe27b7e4d 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -5,7 +5,7 @@ import space.kscience.kmath.ast.MST import space.kscience.kmath.ast.MstAlgebra import space.kscience.kmath.ast.MstExpression import space.kscience.kmath.expressions.DifferentiableExpression -import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.NumericAlgebra /** diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/DataFit.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/DataFit.kt index e9a5dea86..70dd8417c 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/DataFit.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/DataFit.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.optimization import space.kscience.kmath.expressions.DifferentiableExpression -import space.kscience.kmath.expressions.StringSymbol -import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.misc.StringSymbol +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.structures.Buffer public interface DataFit : Optimization { diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt index bf37f5c64..02aa9e9bb 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt @@ -1,6 +1,11 @@ package space.kscience.kmath.optimization -import space.kscience.kmath.expressions.* +import space.kscience.kmath.expressions.AutoDiffProcessor +import space.kscience.kmath.expressions.DifferentiableExpression +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.ExpressionAlgebra +import space.kscience.kmath.misc.StringSymbol +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.indices diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt index 370274b41..0b13e07ba 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.optimization -import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.misc.Symbol public interface OptimizationFeature From 5e94610e2862fc2ecfe5e4f9e709ecc2ab3f428a Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 19 Mar 2021 17:51:30 +0300 Subject: [PATCH 113/393] imp full and remove copypaste in geners --- .../kscience/kmath/tensors/BufferedTensor.kt | 34 +++++++------------ .../kmath/tensors/DoubleTensorAlgebra.kt | 34 +++++++------------ .../kscience/kmath/tensors/TensorAlgebra.kt | 12 +++---- 3 files changed, 31 insertions(+), 49 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt index c48e47f4c..b9ebf578a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt @@ -31,28 +31,6 @@ public open class BufferedTensor( override fun hashCode(): Int = 0 - // todo rename to vector - public inline fun forEachVector(vectorAction : (MutableStructure1D) -> Unit): Unit { - check(shape.size >= 1) {"todo"} - val vectorOffset = strides.strides[0] - val vectorShape = intArrayOf(shape.last()) - for (offset in 0 until numel step vectorOffset) { - val vector = BufferedTensor(vectorShape, buffer, offset).as1D() - vectorAction(vector) - } - } - - public inline fun forEachMatrix(matrixAction : (MutableStructure2D) -> Unit): Unit { - check(shape.size >= 2) {"todo"} - val matrixOffset = strides.strides[1] - val matrixShape = intArrayOf(shape[shape.size - 2], shape.last()) //todo better way? - for (offset in 0 until numel step matrixOffset) { - val matrix = BufferedTensor(matrixShape, buffer, offset).as2D() - matrixAction(matrix) - } - } - // todo remove code copy-pasting - public fun vectorSequence(): Sequence> = sequence { check(shape.size >= 1) {"todo"} val vectorOffset = strides.strides[0] @@ -73,6 +51,18 @@ public open class BufferedTensor( } } + public inline fun forEachVector(vectorAction : (MutableStructure1D) -> Unit): Unit { + for (vector in vectorSequence()){ + vectorAction(vector) + } + } + + public inline fun forEachMatrix(matrixAction : (MutableStructure2D) -> Unit): Unit { + for (matrix in matrixSequence()){ + matrixAction(matrix) + } + } + } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt index 675be2f33..6459f4510 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt @@ -10,23 +10,24 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra> { - public fun zeros(shape: IntArray): TensorType - public fun TensorType.zeroesLike(): TensorType // mb it shouldn't be tensor but algebra method (like in numpy/torch) ? - public fun ones(shape: IntArray): TensorType - public fun TensorType.onesLike(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.full.html public fun full(shape: IntArray, value: T): TensorType + public fun ones(shape: IntArray): TensorType + public fun zeros(shape: IntArray): TensorType + //https://pytorch.org/docs/stable/generated/torch.full_like.html#torch.full_like public fun TensorType.fullLike(value: T): TensorType + public fun TensorType.zeroesLike(): TensorType + public fun TensorType.onesLike(): TensorType + //https://pytorch.org/docs/stable/generated/torch.eye.html public fun eye(n: Int): TensorType From 274be613302d8cdef5f8a81fc8aeee5c88bf8ccd Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 19 Mar 2021 19:40:17 +0000 Subject: [PATCH 114/393] Explicit broadcasting enforced --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 2 +- .../BroadcastDoubleTensorAlgebra.kt} | 151 ++++++++++-------- .../tensors/{ => core}/BufferedTensor.kt | 12 +- .../{ => core}/DoubleAnalyticTensorAlgebra.kt | 4 +- .../DoubleLinearOpsTensorAlgebra.kt | 4 +- .../{ => core}/DoubleOrderedTensorAlgebra.kt | 4 +- .../DoubleReduceOpsTensorAlgebra.kt | 6 +- .../tensors/{ => core}/DoubleTensorAlgebra.kt | 107 +++++++------ .../kscience/kmath/tensors/core/checks.kt | 67 ++++++++ .../kscience/kmath/tensors/core/utils.kt | 36 +++++ .../kmath/tensors/TestDoubleTensorAlgebra.kt | 105 ------------ .../kmath/tensors/core/TestBroadcasting.kt | 82 ++++++++++ .../tensors/{ => core}/TestDoubleTensor.kt | 10 +- .../tensors/core/TestDoubleTensorAlgebra.kt | 50 ++++++ 14 files changed, 407 insertions(+), 233 deletions(-) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{utils.kt => core/BroadcastDoubleTensorAlgebra.kt} (50%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => core}/BufferedTensor.kt (88%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => core}/DoubleAnalyticTensorAlgebra.kt (96%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => core}/DoubleLinearOpsTensorAlgebra.kt (96%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => core}/DoubleOrderedTensorAlgebra.kt (89%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => core}/DoubleReduceOpsTensorAlgebra.kt (68%) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => core}/DoubleTensorAlgebra.kt (77%) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt delete mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt rename kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/{ => core}/TestDoubleTensor.kt (74%) create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index 2e1c4a92c..94176564c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -17,7 +17,7 @@ public interface LinearOpsTensorAlgebra, Inde public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun luPivot(lu: TensorType, pivots: IntTensor): Triple + public fun luPivot(lu: TensorType, pivots: IndexTensorType): Triple //https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd public fun TensorType.svd(): Triple diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt similarity index 50% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index e7e043463..a4767a612 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -1,10 +1,91 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core -import space.kscience.kmath.structures.* import kotlin.math.max +public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { + + override fun DoubleTensor.plus(other: DoubleTensor): DoubleTensor { + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + newThis.buffer.array()[i] + newOther.buffer.array()[i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun DoubleTensor.plusAssign(other: DoubleTensor) { + val newOther = broadcastTo(other, this.shape) + for (i in 0 until this.strides.linearSize) { + this.buffer.array()[this.bufferStart + i] += + newOther.buffer.array()[this.bufferStart + i] + } + } + + override fun DoubleTensor.minus(other: DoubleTensor): DoubleTensor { + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + newThis.buffer.array()[i] - newOther.buffer.array()[i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun DoubleTensor.minusAssign(other: DoubleTensor) { + val newOther = broadcastTo(other, this.shape) + for (i in 0 until this.strides.linearSize) { + this.buffer.array()[this.bufferStart + i] -= + newOther.buffer.array()[this.bufferStart + i] + } + } + + override fun DoubleTensor.times(other: DoubleTensor): DoubleTensor { + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + newThis.buffer.array()[newOther.bufferStart + i] * + newOther.buffer.array()[newOther.bufferStart + i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun DoubleTensor.timesAssign(other: DoubleTensor) { + val newOther = broadcastTo(other, this.shape) + for (i in 0 until this.strides.linearSize) { + this.buffer.array()[this.bufferStart + i] *= + newOther.buffer.array()[this.bufferStart + i] + } + } + + override fun DoubleTensor.div(other: DoubleTensor): DoubleTensor { + val broadcast = broadcastTensors(this, other) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + newThis.buffer.array()[newOther.bufferStart + i] / + newOther.buffer.array()[newOther.bufferStart + i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun DoubleTensor.divAssign(other: DoubleTensor) { + val newOther = broadcastTo(other, this.shape) + for (i in 0 until this.strides.linearSize) { + this.buffer.array()[this.bufferStart + i] /= + newOther.buffer.array()[this.bufferStart + i] + } + } + +} + +public inline fun broadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorAlgebra.() -> R): R = + BroadcastDoubleTensorAlgebra().block() + internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { + println(shapes) var totalDim = 0 for (shape in shapes) { totalDim = max(totalDim, shape.size) @@ -99,68 +180,4 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List, - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkDot(a: TensorType, b: TensorType): Unit { - val sa = a.shape - val sb = b.shape - val na = sa.size - val nb = sb.size - var status: Boolean - if (nb == 1) { - status = sa.last() == sb[0] - } else { - status = sa.last() == sb[nb - 2] - if ((na > 2) and (nb > 2)) { - status = status and - (sa.take(nb - 2).toIntArray() contentEquals sb.take(nb - 2).toIntArray()) - } - } - check(status) { "Incompatible shapes $sa and $sb for dot product" } -} - -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkTranspose(dim: Int, i: Int, j: Int): Unit = - check((i < dim) and (j < dim)) { - "Cannot transpose $i to $j for a tensor of dim $dim" - } - -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = - check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) - -/** - * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. - */ -internal fun Buffer.array(): IntArray = when(this) { - is IntBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to IntArray") -} - -/** - * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. - */ -internal fun Buffer.array(): LongArray = when(this) { - is LongBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to LongArray") -} - -/** - * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. - */ -internal fun Buffer.array(): FloatArray = when(this) { - is FloatBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to FloatArray") -} - -/** - * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. - */ -internal fun Buffer.array(): DoubleArray = when(this) { - is RealBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") -} +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt similarity index 88% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index c48e47f4c..cbfb15be0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,8 +1,10 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core import space.kscience.kmath.linear.Matrix import space.kscience.kmath.nd.* import space.kscience.kmath.structures.* +import space.kscience.kmath.tensors.TensorStrides +import space.kscience.kmath.tensors.TensorStructure public open class BufferedTensor( @@ -76,25 +78,25 @@ public open class BufferedTensor( } -public class IntTensor( +public class IntTensor internal constructor( shape: IntArray, buffer: IntArray, offset: Int = 0 ) : BufferedTensor(shape, IntBuffer(buffer), offset) -public class LongTensor( +public class LongTensor internal constructor( shape: IntArray, buffer: LongArray, offset: Int = 0 ) : BufferedTensor(shape, LongBuffer(buffer), offset) -public class FloatTensor( +public class FloatTensor internal constructor( shape: IntArray, buffer: FloatArray, offset: Int = 0 ) : BufferedTensor(shape, FloatBuffer(buffer), offset) -public class DoubleTensor( +public class DoubleTensor internal constructor( shape: IntArray, buffer: DoubleArray, offset: Int = 0 diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt similarity index 96% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt index 5349a9923..a34fe4b6c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt @@ -1,4 +1,6 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.tensors.AnalyticTensorAlgebra public class DoubleAnalyticTensorAlgebra: AnalyticTensorAlgebra, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt similarity index 96% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 3f44305b1..8a16dc3ed 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,4 +1,6 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.tensors.LinearOpsTensorAlgebra public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt similarity index 89% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt index bd6bcfe8f..a6bea59f4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleOrderedTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt @@ -1,4 +1,6 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.tensors.OrderedTensorAlgebra public open class DoubleOrderedTensorAlgebra: OrderedTensorAlgebra, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt similarity index 68% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt index 00d9b3ff8..9a8aa9ebf 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleReduceOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt @@ -1,8 +1,10 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.tensors.ReduceOpsTensorAlgebra public class DoubleReduceOpsTensorAlgebra: DoubleTensorAlgebra(), - ReduceOpsTensorAlgebra { + ReduceOpsTensorAlgebra { override fun DoubleTensor.value(): Double { check(this.shape contentEquals intArrayOf(1)) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt similarity index 77% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 675be2f33..9decc0e6a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,8 +1,18 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { + public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor { + checkEmptyShape(shape) + checkEmptyDoubleBuffer(buffer) + checkBufferShapeConsistency(shape, buffer) + return DoubleTensor(shape, buffer, 0) + } + + override operator fun DoubleTensor.get(i: Int): DoubleTensor { val lastShape = this.shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) @@ -53,13 +63,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.array()[i] + newOther.buffer.array()[i] + checkShapesCompatible(this, other) + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.array()[i] + other.buffer.array()[i] } - return DoubleTensor(newThis.shape, resBuffer) + return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.plusAssign(value: Double) { @@ -69,10 +77,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.array()[i] - newOther.buffer.array()[i] + checkShapesCompatible(this, other) + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.array()[i] - other.buffer.array()[i] } - return DoubleTensor(newThis.shape, resBuffer) + return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.minusAssign(value: Double) { @@ -107,10 +113,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - newThis.buffer.array()[newOther.bufferStart + i] * - newOther.buffer.array()[newOther.bufferStart + i] + checkShapesCompatible(this, other) + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.array()[other.bufferStart + i] * + other.buffer.array()[other.bufferStart + i] } - return DoubleTensor(newThis.shape, resBuffer) + return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.timesAssign(value: Double) { @@ -142,10 +145,40 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + this.buffer.array()[this.bufferStart + i] / value + } + return DoubleTensor(this.shape, resBuffer) + } + + override fun DoubleTensor.div(other: DoubleTensor): DoubleTensor { + checkShapesCompatible(this, other) + val resBuffer = DoubleArray(this.strides.linearSize) { i -> + this.buffer.array()[other.bufferStart + i] / + other.buffer.array()[other.bufferStart + i] + } + return DoubleTensor(this.shape, resBuffer) + } + + override fun DoubleTensor.divAssign(value: Double) { + for (i in 0 until this.strides.linearSize) { + this.buffer.array()[this.bufferStart + i] /= value + } + } + + override fun DoubleTensor.divAssign(other: DoubleTensor) { + checkShapesCompatible(this, other) + for (i in 0 until this.strides.linearSize) { + this.buffer.array()[this.bufferStart + i] /= + other.buffer.array()[this.bufferStart + i] } } @@ -229,27 +262,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra DoubleTensorAlgebra(block: DoubleTensorAlgebra.() -> R): R = - DoubleTensorAlgebra().block() \ No newline at end of file + DoubleTensorAlgebra().block() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt new file mode 100644 index 000000000..f1ae89490 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -0,0 +1,67 @@ +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.tensors.TensorAlgebra +import space.kscience.kmath.tensors.TensorStructure + + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkEmptyShape(shape: IntArray): Unit = + check(shape.isNotEmpty()) { + "Illegal empty shape provided" + } + +internal inline fun < TensorType : TensorStructure, + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = + check(buffer.isNotEmpty()) { + "Illegal empty buffer provided" + } + +internal inline fun < TensorType : TensorStructure, + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = + check(buffer.size == shape.reduce(Int::times)) { + "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" + } + + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkShapesCompatible(a: TensorType, b: TensorType): Unit = + check(a.shape contentEquals b.shape) { + "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " + } + + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkDot(a: TensorType, b: TensorType): Unit { + val sa = a.shape + val sb = b.shape + val na = sa.size + val nb = sb.size + var status: Boolean + if (nb == 1) { + status = sa.last() == sb[0] + } else { + status = sa.last() == sb[nb - 2] + if ((na > 2) and (nb > 2)) { + status = status and + (sa.take(nb - 2).toIntArray() contentEquals sb.take(nb - 2).toIntArray()) + } + } + check(status) { "Incompatible shapes ${sa.toList()} and ${sb.toList()} provided for dot product" } +} + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkTranspose(dim: Int, i: Int, j: Int): Unit = + check((i < dim) and (j < dim)) { + "Cannot transpose $i to $j for a tensor of dim $dim" + } + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = + check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt new file mode 100644 index 000000000..69c8afde5 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -0,0 +1,36 @@ +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.structures.* + + +/** + * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.array(): IntArray = when (this) { + is IntBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to IntArray") +} + +/** + * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.array(): LongArray = when (this) { + is LongBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to LongArray") +} + +/** + * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.array(): FloatArray = when (this) { + is FloatBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to FloatArray") +} + +/** + * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. + */ +internal fun Buffer.array(): DoubleArray = when (this) { + is RealBuffer -> array + else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") +} diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt deleted file mode 100644 index a060a970f..000000000 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensorAlgebra.kt +++ /dev/null @@ -1,105 +0,0 @@ -package space.kscience.kmath.tensors - - -import kotlin.test.Test -import kotlin.test.assertTrue - -class TestDoubleTensorAlgebra { - - @Test - fun doublePlus() = DoubleTensorAlgebra { - val tensor = DoubleTensor(intArrayOf(2), doubleArrayOf(1.0, 2.0)) - val res = 10.0 + tensor - assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0,12.0)) - } - - @Test - fun transpose1x1() = DoubleTensorAlgebra { - val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(0.0)) - val res = tensor.transpose(0, 0) - - assertTrue(res.buffer.array() contentEquals doubleArrayOf(0.0)) - assertTrue(res.shape contentEquals intArrayOf(1)) - } - - @Test - fun transpose3x2() = DoubleTensorAlgebra { - val tensor = DoubleTensor(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val res = tensor.transpose(1, 0) - - assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) - assertTrue(res.shape contentEquals intArrayOf(2, 3)) - } - - @Test - fun transpose1x2x3() = DoubleTensorAlgebra { - val tensor = DoubleTensor(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val res01 = tensor.transpose(0, 1) - val res02 = tensor.transpose(0, 2) - val res12 = tensor.transpose(1, 2) - - assertTrue(res01.shape contentEquals intArrayOf(2, 1, 3)) - assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) - assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2)) - - assertTrue(res01.buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res02.buffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) - assertTrue(res12.buffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) - } - - @Test - fun broadcastShapes() = DoubleTensorAlgebra { - assertTrue(broadcastShapes( - intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) - ) contentEquals intArrayOf(1, 2, 3)) - - assertTrue(broadcastShapes( - intArrayOf(6, 7), intArrayOf(5, 6, 1), intArrayOf(7,), intArrayOf(5, 1, 7) - ) contentEquals intArrayOf(5, 6, 7)) - } - - @Test - fun broadcastTo() = DoubleTensorAlgebra { - val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - - val res = broadcastTo(tensor2, tensor1.shape) - assertTrue(res.shape contentEquals intArrayOf(2, 3)) - assertTrue(res.buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) - } - - @Test - fun broadcastTensors() = DoubleTensorAlgebra { - val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) - - val res = broadcastTensors(tensor1, tensor2, tensor3) - - assertTrue(res[0].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) - - assertTrue(res[0].buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res[1].buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) - assertTrue(res[2].buffer.array() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) - } - - @Test - fun minusTensor() = DoubleTensorAlgebra { - val tensor1 = DoubleTensor(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val tensor2 = DoubleTensor(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) - val tensor3 = DoubleTensor(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) - - assertTrue((tensor2 - tensor1).shape contentEquals intArrayOf(2, 3)) - assertTrue((tensor2 - tensor1).buffer.array() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) - - assertTrue((tensor3 - tensor1).shape contentEquals intArrayOf(1, 2, 3)) - assertTrue((tensor3 - tensor1).buffer.array() - contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0)) - - assertTrue((tensor3 - tensor2).shape contentEquals intArrayOf(1, 1, 3)) - assertTrue((tensor3 - tensor2).buffer.array() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) - } - -} \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt new file mode 100644 index 000000000..2633229ea --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -0,0 +1,82 @@ +package space.kscience.kmath.tensors.core + +import kotlin.test.Test +import kotlin.test.assertTrue + +class TestBroadcasting { + + @Test + fun broadcastShapes() = DoubleTensorAlgebra { + assertTrue( + broadcastShapes( + intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) + ) contentEquals intArrayOf(1, 2, 3) + ) + + assertTrue( + broadcastShapes( + intArrayOf(6, 7), intArrayOf(5, 6, 1), intArrayOf(7), intArrayOf(5, 1, 7) + ) contentEquals intArrayOf(5, 6, 7) + ) + } + + @Test + fun broadcastTo() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + + val res = broadcastTo(tensor2, tensor1.shape) + assertTrue(res.shape contentEquals intArrayOf(2, 3)) + assertTrue(res.buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + } + + @Test + fun broadcastTensors() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + + val res = broadcastTensors(tensor1, tensor2, tensor3) + + assertTrue(res[0].shape contentEquals intArrayOf(1, 2, 3)) + assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) + assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) + + assertTrue(res[0].buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + assertTrue(res[2].buffer.array() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) + } + + @Test + fun minusTensor() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + + val tensor21 = broadcastDoubleTensorAlgebra { + tensor2 - tensor1 + } + + val tensor31 = broadcastDoubleTensorAlgebra { + tensor3 - tensor1 + } + + val tensor32 = broadcastDoubleTensorAlgebra { + tensor3 - tensor2 + } + + + assertTrue(tensor21.shape contentEquals intArrayOf(2, 3)) + assertTrue(tensor21.buffer.array() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) + + assertTrue(tensor31.shape contentEquals intArrayOf(1, 2, 3)) + assertTrue( + tensor31.buffer.array() + contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0) + ) + + assertTrue(tensor32.shape contentEquals intArrayOf(1, 1, 3)) + assertTrue(tensor32.buffer.array() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) + } + +} \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt similarity index 74% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt rename to kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 6b20027c7..b12b08b52 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,4 +1,4 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.core import space.kscience.kmath.nd.as1D @@ -13,20 +13,20 @@ class TestDoubleTensor { @Test fun valueTest() = DoubleReduceOpsTensorAlgebra { val value = 12.5 - val tensor = DoubleTensor(intArrayOf(1), doubleArrayOf(value)) + val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @Test - fun stridesTest(){ - val tensor = DoubleTensor(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) + fun stridesTest() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) assertEquals(tensor[intArrayOf(0,1)], 5.8) assertTrue(tensor.elements().map{ it.second }.toList().toDoubleArray() contentEquals tensor.buffer.toDoubleArray()) } @Test fun getTest() = DoubleTensorAlgebra { - val tensor = DoubleTensor(intArrayOf(1,2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) + val tensor = fromArray(intArrayOf(1,2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) val matrix = tensor[0].as2D() assertEquals(matrix[0,1], 5.8) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt new file mode 100644 index 000000000..8b4d5ca16 --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -0,0 +1,50 @@ +package space.kscience.kmath.tensors.core + + +import kotlin.test.Test +import kotlin.test.assertTrue + +class TestDoubleTensorAlgebra { + + @Test + fun doublePlus() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0)) + val res = 10.0 + tensor + assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0, 12.0)) + } + + @Test + fun transpose1x1() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(1), doubleArrayOf(0.0)) + val res = tensor.transpose(0, 0) + + assertTrue(res.buffer.array() contentEquals doubleArrayOf(0.0)) + assertTrue(res.shape contentEquals intArrayOf(1)) + } + + @Test + fun transpose3x2() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val res = tensor.transpose(1, 0) + + assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) + assertTrue(res.shape contentEquals intArrayOf(2, 3)) + } + + @Test + fun transpose1x2x3() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val res01 = tensor.transpose(0, 1) + val res02 = tensor.transpose(0, 2) + val res12 = tensor.transpose(1, 2) + + assertTrue(res01.shape contentEquals intArrayOf(2, 1, 3)) + assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) + assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2)) + + assertTrue(res01.buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res02.buffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res12.buffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + } + +} \ No newline at end of file From 3535e512483b74f00867858b18e38a2150f3451c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 19 Mar 2021 19:52:58 +0000 Subject: [PATCH 115/393] Broadcasting as its own algebra --- .../core/BroadcastDoubleTensorAlgebra.kt | 2 +- .../kmath/tensors/core/TestBroadcasting.kt | 17 ++++------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index a4767a612..20f64f469 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -80,7 +80,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { } -public inline fun broadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorAlgebra.() -> R): R = +public inline fun BroadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorAlgebra.() -> R): R = BroadcastDoubleTensorAlgebra().block() diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 2633229ea..73e3993a1 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -48,23 +48,14 @@ class TestBroadcasting { } @Test - fun minusTensor() = DoubleTensorAlgebra { + fun minusTensor() = BroadcastDoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) - val tensor21 = broadcastDoubleTensorAlgebra { - tensor2 - tensor1 - } - - val tensor31 = broadcastDoubleTensorAlgebra { - tensor3 - tensor1 - } - - val tensor32 = broadcastDoubleTensorAlgebra { - tensor3 - tensor2 - } - + val tensor21 = tensor2 - tensor1 + val tensor31 = tensor3 - tensor1 + val tensor32 = tensor3 - tensor2 assertTrue(tensor21.shape contentEquals intArrayOf(2, 3)) assertTrue(tensor21.buffer.array() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) From 93d3cb47bed67d95c75d6e9f54283f7428dd150e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 19 Mar 2021 20:10:08 +0000 Subject: [PATCH 116/393] Testing linear structure --- .../kscience/kmath/tensors/TensorAlgebra.kt | 12 +++---- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 35 ++++++++----------- .../tensors/core/TestDoubleTensorAlgebra.kt | 32 +++++++++++++++++ 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 7ec920d88..1673657d3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -3,19 +3,17 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { + //https://pytorch.org/docs/stable/generated/torch.full.html + public fun full(value: T, shape: IntArray): TensorType + + //https://pytorch.org/docs/stable/generated/torch.full_like.html#torch.full_like + public fun TensorType.fullLike(value: T): TensorType public fun zeros(shape: IntArray): TensorType public fun TensorType.zeroesLike(): TensorType // mb it shouldn't be tensor but algebra method (like in numpy/torch) ? public fun ones(shape: IntArray): TensorType public fun TensorType.onesLike(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.full.html - public fun full(shape: IntArray, value: T): TensorType - - //https://pytorch.org/docs/stable/generated/torch.full_like.html#torch.full_like - public fun TensorType.fullLike(value: T): TensorType - //https://pytorch.org/docs/stable/generated/torch.eye.html public fun eye(n: Int): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 9decc0e6a..1c156b4e3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -20,23 +20,25 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Date: Fri, 19 Mar 2021 20:32:57 +0000 Subject: [PATCH 117/393] merge PR --- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 465c2ddc1..875f21687 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -12,7 +12,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra>>>>>> ups/feature/tensor-algebra:kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt override fun DoubleTensor.fullLike(value: Double): DoubleTensor { val shape = this.shape val buffer = DoubleArray(this.strides.linearSize) { value } return DoubleTensor(shape, buffer) } -<<<<<<< HEAD:kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/DoubleTensorAlgebra.kt - override fun DoubleTensor.zeroesLike(): DoubleTensor = this.fullLike(0.0) - -======= override fun zeros(shape: IntArray): DoubleTensor = full(0.0, shape) override fun DoubleTensor.zeroesLike(): DoubleTensor = this.fullLike(0.0) override fun ones(shape: IntArray): DoubleTensor = full(1.0, shape) ->>>>>>> ups/feature/tensor-algebra:kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt override fun DoubleTensor.onesLike(): DoubleTensor = this.fullLike(1.0) override fun eye(n: Int): DoubleTensor { @@ -71,7 +53,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra other.buffer.array()[other.bufferStart + i] + this From b7e1349eadc0cfe9b573006c79e714333655a2d1 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sat, 20 Mar 2021 18:59:54 +0000 Subject: [PATCH 118/393] atanh as example --- .../kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt index a34fe4b6c..8a579b7da 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.AnalyticTensorAlgebra +import kotlin.math.* public class DoubleAnalyticTensorAlgebra: AnalyticTensorAlgebra, @@ -63,7 +64,11 @@ public class DoubleAnalyticTensorAlgebra: } override fun DoubleTensor.atanh(): DoubleTensor { - TODO("Not yet implemented") + return DoubleTensor( + this.shape, + this.buffer.array().map(::atanh).toDoubleArray(), + this.bufferStart + ) } override fun DoubleTensor.ceil(): DoubleTensor { From 94e5ee4a6de020d77c49ce57e7795d3a33abe80e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sun, 21 Mar 2021 08:01:52 +0000 Subject: [PATCH 119/393] TensorLinearStructure introduced --- .../space/kscience/kmath/nd/StructureND.kt | 17 +++---- .../core/BroadcastDoubleTensorAlgebra.kt | 24 +++++----- .../kmath/tensors/core/BufferedTensor.kt | 18 ++++---- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 44 +++++++++---------- .../TensorLinearStructure.kt} | 33 ++++++++------ 5 files changed, 69 insertions(+), 67 deletions(-) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/{TensorStrides.kt => core/TensorLinearStructure.kt} (55%) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index 86b867130..f28d29e47 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -177,7 +177,7 @@ public interface Strides { /** * Array strides */ - public val strides: IntArray + public val strides: List /** * Get linear index from multidimensional index @@ -209,12 +209,6 @@ public interface Strides { } } -internal inline fun offsetFromIndex(index: IntArray, shape: IntArray, strides: IntArray): Int = - index.mapIndexed { i, value -> - if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})") - value * strides[i] - }.sum() - /** * Simple implementation of [Strides]. */ @@ -225,7 +219,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) : /** * Strides for memory access */ - override val strides: IntArray by lazy { + override val strides: List by lazy { sequence { var current = 1 yield(1) @@ -234,10 +228,13 @@ public class DefaultStrides private constructor(override val shape: IntArray) : current *= it yield(current) } - }.toList().toIntArray() + }.toList() } - override fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides) + override fun offset(index: IntArray): Int = index.mapIndexed { i, value -> + if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})") + value * strides[i] + }.sum() override fun index(offset: Int): IntArray { val res = IntArray(shape.size) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index 20f64f469..4bfbe5863 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -8,7 +8,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(this, other) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> newThis.buffer.array()[i] + newOther.buffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) @@ -16,7 +16,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun DoubleTensor.plusAssign(other: DoubleTensor) { val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] += newOther.buffer.array()[this.bufferStart + i] } @@ -26,7 +26,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(this, other) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> newThis.buffer.array()[i] - newOther.buffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) @@ -34,7 +34,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun DoubleTensor.minusAssign(other: DoubleTensor) { val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] -= newOther.buffer.array()[this.bufferStart + i] } @@ -44,7 +44,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(this, other) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> newThis.buffer.array()[newOther.bufferStart + i] * newOther.buffer.array()[newOther.bufferStart + i] } @@ -53,7 +53,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun DoubleTensor.timesAssign(other: DoubleTensor) { val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] *= newOther.buffer.array()[this.bufferStart + i] } @@ -63,7 +63,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(this, other) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.strides.linearSize) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> newThis.buffer.array()[newOther.bufferStart + i] / newOther.buffer.array()[newOther.bufferStart + i] } @@ -72,7 +72,7 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun DoubleTensor.divAssign(other: DoubleTensor) { val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] /= newOther.buffer.array()[this.bufferStart + i] } @@ -130,7 +130,7 @@ internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): Doubl } for (linearIndex in 0 until n) { - val totalMultiIndex = resTensor.strides.index(linearIndex) + val totalMultiIndex = resTensor.linearStructure.index(linearIndex) val curMultiIndex = tensor.shape.copyOf() val offset = totalMultiIndex.size - curMultiIndex.size @@ -143,7 +143,7 @@ internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): Doubl } } - val curLinearIndex = tensor.strides.offset(curMultiIndex) + val curLinearIndex = tensor.linearStructure.offset(curMultiIndex) resTensor.buffer.array()[linearIndex] = tensor.buffer.array()[tensor.bufferStart + curLinearIndex] } @@ -159,7 +159,7 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List( internal val bufferStart: Int ) : TensorStructure { - public val strides: TensorStrides - get() = TensorStrides(shape) + public val linearStructure: TensorLinearStructure + get() = TensorLinearStructure(shape) public val numel: Int - get() = strides.linearSize + get() = linearStructure.size - override fun get(index: IntArray): T = buffer[bufferStart + strides.offset(index)] + override fun get(index: IntArray): T = buffer[bufferStart + linearStructure.offset(index)] override fun set(index: IntArray, value: T) { - buffer[bufferStart + strides.offset(index)] = value + buffer[bufferStart + linearStructure.offset(index)] = value } - override fun elements(): Sequence> = strides.indices().map { + override fun elements(): Sequence> = linearStructure.indices().map { it to this[it] } @@ -35,7 +33,7 @@ public open class BufferedTensor( public fun vectorSequence(): Sequence> = sequence { check(shape.size >= 1) {"todo"} - val vectorOffset = strides.strides[0] + val vectorOffset = linearStructure.strides[0] val vectorShape = intArrayOf(shape.last()) for (offset in 0 until numel step vectorOffset) { val vector = BufferedTensor(vectorShape, buffer, offset).as1D() @@ -45,7 +43,7 @@ public open class BufferedTensor( public fun matrixSequence(): Sequence> = sequence { check(shape.size >= 2) {"todo"} - val matrixOffset = strides.strides[1] + val matrixOffset = linearStructure.strides[1] val matrixShape = intArrayOf(shape[shape.size - 2], shape.last()) //todo better way? for (offset in 0 until numel step matrixOffset) { val matrix = BufferedTensor(matrixShape, buffer, offset).as2D() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 875f21687..385118d97 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -27,7 +27,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(other.linearStructure.size) { i -> other.buffer.array()[other.bufferStart + i] + this } return DoubleTensor(other.shape, resBuffer) @@ -64,35 +64,35 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[i] + other.buffer.array()[i] } return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.plusAssign(value: Double) { - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] += value } } override fun DoubleTensor.plusAssign(other: DoubleTensor) { checkShapesCompatible(this, other) - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] += other.buffer.array()[this.bufferStart + i] } } override fun Double.minus(other: DoubleTensor): DoubleTensor { - val resBuffer = DoubleArray(other.strides.linearSize) { i -> + val resBuffer = DoubleArray(other.linearStructure.size) { i -> this - other.buffer.array()[other.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } override fun DoubleTensor.minus(value: Double): DoubleTensor { - val resBuffer = DoubleArray(this.strides.linearSize) { i -> + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[this.bufferStart + i] - value } return DoubleTensor(this.shape, resBuffer) @@ -100,28 +100,28 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[i] - other.buffer.array()[i] } return DoubleTensor(this.shape, resBuffer) } override fun DoubleTensor.minusAssign(value: Double) { - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] -= value } } override fun DoubleTensor.minusAssign(other: DoubleTensor) { checkShapesCompatible(this, other) - for (i in 0 until this.strides.linearSize) { + for (i in 0 until this.linearStructure.size) { this.buffer.array()[this.bufferStart + i] -= other.buffer.array()[this.bufferStart + i] } } override fun Double.times(other: DoubleTensor): DoubleTensor { - val resBuffer = DoubleArray(other.strides.linearSize) { i -> + val resBuffer = DoubleArray(other.linearStructure.size) { i -> other.buffer.array()[other.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) @@ -131,7 +131,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[other.bufferStart + i] * other.buffer.array()[other.bufferStart + i] } @@ -139,21 +139,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[this.bufferStart + i] / value } return DoubleTensor(this.shape, resBuffer) @@ -161,7 +161,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[other.bufferStart + i] / other.buffer.array()[other.bufferStart + i] } @@ -169,21 +169,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + val resBuffer = DoubleArray(this.linearStructure.size) { i -> this.buffer.array()[this.bufferStart + i].unaryMinus() } return DoubleTensor(this.shape, resBuffer) @@ -191,7 +191,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra + if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})") + value * strides[i] + }.sum() + internal inline fun stridesFromShape(shape: IntArray): IntArray { val nDim = shape.size val res = IntArray(nDim) @@ -35,7 +39,7 @@ internal inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): return res } -internal inline fun nextIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { +internal inline fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { val res = index.copyOf() var current = nDim - 1 var carry = 0 @@ -47,26 +51,29 @@ internal inline fun nextIndex(index: IntArray, shape: IntArray, nDim: Int): IntA res[current] = 0 } current-- - } while(carry != 0 && current >= 0) + } while (carry != 0 && current >= 0) return res } - -public class TensorStrides(override val shape: IntArray): Strides +public class TensorLinearStructure(public val shape: IntArray) { - override val strides: IntArray + public val strides: IntArray get() = stridesFromShape(shape) - override fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides) + public fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides) - override fun index(offset: Int): IntArray = + public fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) - override fun nextIndex(index: IntArray): IntArray = - nextIndex(index, shape, shape.size) + public fun stepIndex(index: IntArray): IntArray = + stepIndex(index, shape, shape.size) - override val linearSize: Int + public val size: Int get() = shape.reduce(Int::times) + + public fun indices(): Sequence = (0 until size).asSequence().map { + index(it) + } } \ No newline at end of file From d8ef190ed8912476aaf7901431cc7e24d6449d94 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sun, 21 Mar 2021 08:07:17 +0000 Subject: [PATCH 120/393] UnaryPlus fails API check --- .../kotlin/space/kscience/kmath/nd/StructureND.kt | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index f28d29e47..78eac1809 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -189,11 +189,6 @@ public interface Strides { */ public fun index(offset: Int): IntArray - /** - * Get next multidimensional index from the current multidimensional index - */ - public fun nextIndex(index: IntArray): IntArray - /** * The size of linear buffer to accommodate all elements of ND-structure corresponding to strides */ @@ -232,7 +227,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) : } override fun offset(index: IntArray): Int = index.mapIndexed { i, value -> - if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})") + if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${this.shape[i]})") value * strides[i] }.sum() @@ -250,10 +245,6 @@ public class DefaultStrides private constructor(override val shape: IntArray) : return res } - override fun nextIndex(index: IntArray): IntArray { - TODO("Not yet implemented") - } - override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is DefaultStrides) return false @@ -275,7 +266,6 @@ public class DefaultStrides private constructor(override val shape: IntArray) : } } - public inline fun StructureND.combine( struct: StructureND, crossinline block: (T, T) -> T, From fa78ed1f45f3598e26d74d21d6f79c623c9e8e8e Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sun, 21 Mar 2021 19:05:11 +0300 Subject: [PATCH 121/393] map and analytic funcions --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 4 +- .../kscience/kmath/tensors/TensorAlgebra.kt | 5 ++ .../kmath/tensors/core/BufferedTensor.kt | 1 + .../core/DoubleAnalyticTensorAlgebra.kt | 73 +++++-------------- .../core/DoubleLinearOpsTensorAlgebra.kt | 63 +++++++++++----- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 39 +++++++++- .../kscience/kmath/tensors/core/checks.kt | 14 +++- 7 files changed, 122 insertions(+), 77 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index 94176564c..c4fa3e0a8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -14,10 +14,10 @@ public interface LinearOpsTensorAlgebra, Inde public fun TensorType.qr(): TensorType //https://pytorch.org/docs/stable/generated/torch.lu.html - public fun TensorType.lu(): Pair + public fun TensorType.lu(tol: T): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun luPivot(lu: TensorType, pivots: IndexTensorType): Triple + public fun luPivot(luTensor: TensorType, pivotsTensor: IndexTensorType): Triple //https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd public fun TensorType.svd(): Triple diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index e41b7546c..8be0dc149 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -3,6 +3,11 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { + public fun TensorType.map(transform: (T) -> T): TensorType + + public fun TensorType.eq(other: TensorType, eqFunction: (T, T) -> Boolean): Boolean + public fun TensorType.contentEquals(other: TensorType, eqFunction: (T, T) -> Boolean): Boolean + //https://pytorch.org/docs/stable/generated/torch.full.html public fun full(value: T, shape: IntArray): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 5a0fc6c75..ca9168c91 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -5,6 +5,7 @@ import space.kscience.kmath.nd.* import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.TensorStrides import space.kscience.kmath.tensors.TensorStructure +import kotlin.math.atanh public open class BufferedTensor( diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt index 8a579b7da..1eb4c3b63 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt @@ -7,77 +7,40 @@ public class DoubleAnalyticTensorAlgebra: AnalyticTensorAlgebra, DoubleOrderedTensorAlgebra() { - override fun DoubleTensor.exp(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.exp(): DoubleTensor = this.map(::exp) - override fun DoubleTensor.log(): DoubleTensor { - TODO("Not yet implemented") - } + // todo log with other base???? + override fun DoubleTensor.log(): DoubleTensor = this.map(::ln) - override fun DoubleTensor.sqrt(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.sqrt(): DoubleTensor = this.map(::sqrt) - override fun DoubleTensor.cos(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.cos(): DoubleTensor = this.map(::cos) - override fun DoubleTensor.acos(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.acos(): DoubleTensor = this.map(::acos) - override fun DoubleTensor.cosh(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.cosh(): DoubleTensor = this.map(::cosh) - override fun DoubleTensor.acosh(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.acosh(): DoubleTensor = this.map(::acosh) - override fun DoubleTensor.sin(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.sin(): DoubleTensor = this.map(::sin) - override fun DoubleTensor.asin(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.asin(): DoubleTensor = this.map(::asin) - override fun DoubleTensor.sinh(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.sinh(): DoubleTensor = this.map(::sinh) - override fun DoubleTensor.asinh(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.asinh(): DoubleTensor = this.map(::asinh) - override fun DoubleTensor.tan(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.tan(): DoubleTensor = this.map(::tan) - override fun DoubleTensor.atan(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.atan(): DoubleTensor = this.map(::atan) - override fun DoubleTensor.tanh(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.tanh(): DoubleTensor = this.map(::tanh) - override fun DoubleTensor.atanh(): DoubleTensor { - return DoubleTensor( - this.shape, - this.buffer.array().map(::atanh).toDoubleArray(), - this.bufferStart - ) - } + override fun DoubleTensor.atanh(): DoubleTensor = this.map(::atanh) - override fun DoubleTensor.ceil(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.ceil(): DoubleTensor = this.map(::ceil) - override fun DoubleTensor.floor(): DoubleTensor { - TODO("Not yet implemented") - } + override fun DoubleTensor.floor(): DoubleTensor = this.map(::floor) override fun DoubleTensor.clamp(min: Double, max: Double): DoubleTensor { TODO("Not yet implemented") diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 8a16dc3ed..e0abc49b7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.LinearOpsTensorAlgebra +import kotlin.math.sqrt public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -10,47 +11,47 @@ public class DoubleLinearOpsTensorAlgebra : TODO("Not yet implemented") } - override fun DoubleTensor.lu(): Pair { + override fun DoubleTensor.lu(tol: Double): Pair { - // todo checks + checkSquareMatrix(shape) - val luTensor = this.copy() + val luTensor = copy() - val n = this.shape.size - val m = this.shape.last() - val pivotsShape = IntArray(n - 1) { i -> this.shape[i] } + val n = shape.size + val m = shape.last() + val pivotsShape = IntArray(n - 1) { i -> shape[i] } val pivotsTensor = IntTensor( pivotsShape, - IntArray(pivotsShape.reduce(Int::times)) { 0 } //todo default??? + IntArray(pivotsShape.reduce(Int::times)) { 0 } ) for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())){ for (row in 0 until m) pivots[row] = row for (i in 0 until m) { - var maxA = -1.0 - var iMax = i + var maxVal = -1.0 + var maxInd = i for (k in i until m) { val absA = kotlin.math.abs(lu[k, i]) - if (absA > maxA) { - maxA = absA - iMax = k + if (absA > maxVal) { + maxVal = absA + maxInd = k } } //todo check singularity - if (iMax != i) { + if (maxInd != i) { val j = pivots[i] - pivots[i] = pivots[iMax] - pivots[iMax] = j + pivots[i] = pivots[maxInd] + pivots[maxInd] = j for (k in 0 until m) { val tmp = lu[i, k] - lu[i, k] = lu[iMax, k] - lu[iMax, k] = tmp + lu[i, k] = lu[maxInd, k] + lu[maxInd, k] = tmp } } @@ -71,6 +72,9 @@ public class DoubleLinearOpsTensorAlgebra : override fun luPivot(luTensor: DoubleTensor, pivotsTensor: IntTensor): Triple { //todo checks + checkSquareMatrix(luTensor.shape) + check(luTensor.shape.dropLast(1).toIntArray() contentEquals pivotsTensor.shape) { "Bed shapes (("} //todo rewrite + val n = luTensor.shape.last() val pTensor = luTensor.zeroesLike() for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.vectorSequence())){ @@ -104,7 +108,30 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.cholesky(): DoubleTensor { - TODO("Not yet implemented") + // todo checks + checkSquareMatrix(shape) + + val n = shape.last() + val lTensor = zeroesLike() + + for ((a, l) in this.matrixSequence().zip(lTensor.matrixSequence())) { + for (i in 0 until n) { + for (j in 0 until i) { + var h = a[i, j] + for (k in 0 until j) { + h -= l[i, k] * l[j, k] + } + l[i, j] = h / l[j, j] + } + var h = a[i, i] + for (j in 0 until i) { + h -= l[i, j] * l[i, j] + } + l[i, i] = sqrt(h) + } + } + + return lTensor } override fun DoubleTensor.qr(): DoubleTensor { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 875f21687..daa8b6d74 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra - +import kotlin.math.abs public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { @@ -277,6 +277,43 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Double): DoubleTensor { + return DoubleTensor( + this.shape, + this.buffer.array().map { transform(it) }.toDoubleArray(), + this.bufferStart + ) + } + + public fun DoubleTensor.contentEquals(other: DoubleTensor, delta: Double = 1e-5): Boolean { + return this.contentEquals(other) { x, y -> abs(x - y) < delta } + } + + public fun DoubleTensor.eq(other: DoubleTensor, delta: Double = 1e-5): Boolean { + return this.eq(other) { x, y -> abs(x - y) < delta } + } + + override fun DoubleTensor.contentEquals(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { + if (!(this.shape contentEquals other.shape)){ + return false + } + return this.eq(other, eqFunction) + } + + override fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { + // todo broadcasting checking + val n = this.strides.linearSize + if (n != other.strides.linearSize){ + return false + } + for (i in 0 until n){ + if (!eqFunction(this.buffer[this.bufferStart + i], other.buffer[other.bufferStart + i])) { + return false + } + } + return true + } + } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index f1ae89490..ec7a123a9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -64,4 +64,16 @@ internal inline fun , internal inline fun , TorchTensorAlgebraType : TensorAlgebra> TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = - check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) \ No newline at end of file + check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) + +internal inline fun , + TorchTensorAlgebraType : TensorAlgebra> + TorchTensorAlgebraType.checkSquareMatrix(shape: IntArray): Unit { + val n = shape.size + check(n >= 2) { + "Expected tensor with 2 or more dimensions, got size $n instead" + } + check(shape[n - 1] == shape[n - 2]) { + "Tensor must be batches of square matrices, but they are ${shape[n - 1]} by ${shape[n - 1]} matrices" + } +} From df402086daeb0b15c78a1a0d987cd46dd5122801 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sun, 21 Mar 2021 19:08:30 +0300 Subject: [PATCH 122/393] init test for analytic algebra --- .../core/TestDoubleAnalyticTensorAlgebra.kt | 35 +++++++++++++++++++ .../tensors/core/TestDoubleTensorAlgebra.kt | 4 +++ 2 files changed, 39 insertions(+) create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt new file mode 100644 index 000000000..8028ce175 --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -0,0 +1,35 @@ +package space.kscience.kmath.tensors.core + +import kotlin.math.abs +import kotlin.math.exp +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class TestDoubleAnalyticTensorAlgebra { + + val shape = intArrayOf(2, 1, 3, 2) + val buffer = doubleArrayOf(27.1, 20.0, 19.84, 23.123, 0.0, 1.0, 3.23, 133.7, 25.3, 100.3, 11.0, 12.012) + val tensor = DoubleTensor(shape, buffer) + + fun DoubleArray.fmap(transform: (Double) -> Double): DoubleArray { + return this.map(transform).toDoubleArray() + } + + fun DoubleArray.deltaEqual(other: DoubleArray, delta: Double = 1e-5): Boolean { + for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) { + if (abs(elem1 - elem2) > delta) { + return false + } + } + return true + } + + @Test + fun testExp() = DoubleAnalyticTensorAlgebra { + tensor.exp().let { + assertTrue { shape contentEquals it.shape } + assertTrue { buffer.fmap(::exp).deltaEqual(it.buffer.array())} + } + } +} \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index ddfba0d59..06aa3ebf7 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -79,4 +79,8 @@ class TestDoubleTensorAlgebra { assertTrue(expected.buffer.array() contentEquals assignResult.buffer.array()) } + @Test + fun testContentEqual() = DoubleTensorAlgebra { + //TODO() + } } \ No newline at end of file From 0365d41f317af785f4963611f4c3899171618720 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sun, 21 Mar 2021 17:57:19 +0000 Subject: [PATCH 123/393] Merged PR --- kmath-core/api/kmath-core.api | 485 ++++++++++++++++++ .../kscience/kmath/tensors/TensorAlgebra.kt | 5 - .../kmath/tensors/core/DoubleTensorAlgebra.kt | 10 +- 3 files changed, 490 insertions(+), 10 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 04325379e..70bec600d 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -972,6 +972,30 @@ public final class space/kscience/kmath/nd/GroupND$DefaultImpls { public static fun unaryPlus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } +public abstract interface class space/kscience/kmath/nd/MutableStructure1D : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/Structure1D, space/kscience/kmath/structures/MutableBuffer { + public abstract fun set ([ILjava/lang/Object;)V +} + +public final class space/kscience/kmath/nd/MutableStructure1D$DefaultImpls { + public static fun get (Lspace/kscience/kmath/nd/MutableStructure1D;[I)Ljava/lang/Object; + public static fun getDimension (Lspace/kscience/kmath/nd/MutableStructure1D;)I + public static fun iterator (Lspace/kscience/kmath/nd/MutableStructure1D;)Ljava/util/Iterator; + public static fun set (Lspace/kscience/kmath/nd/MutableStructure1D;[ILjava/lang/Object;)V +} + +public abstract interface class space/kscience/kmath/nd/MutableStructure2D : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/Structure2D { + public abstract fun set (IILjava/lang/Object;)V +} + +public final class space/kscience/kmath/nd/MutableStructure2D$DefaultImpls { + public static fun elements (Lspace/kscience/kmath/nd/MutableStructure2D;)Lkotlin/sequences/Sequence; + public static fun get (Lspace/kscience/kmath/nd/MutableStructure2D;[I)Ljava/lang/Object; + public static fun getColumns (Lspace/kscience/kmath/nd/MutableStructure2D;)Ljava/util/List; + public static fun getDimension (Lspace/kscience/kmath/nd/MutableStructure2D;)I + public static fun getRows (Lspace/kscience/kmath/nd/MutableStructure2D;)Ljava/util/List; + public static fun getShape (Lspace/kscience/kmath/nd/MutableStructure2D;)[I +} + public abstract interface class space/kscience/kmath/nd/MutableStructureND : space/kscience/kmath/nd/StructureND { public abstract fun set ([ILjava/lang/Object;)V } @@ -1072,6 +1096,7 @@ public final class space/kscience/kmath/nd/Structure1D$DefaultImpls { } public final class space/kscience/kmath/nd/Structure1DKt { + public static final fun as1D (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructure1D; public static final fun as1D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure1D; public static final fun asND (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/nd/Structure1D; } @@ -1101,6 +1126,7 @@ public final class space/kscience/kmath/nd/Structure2D$DefaultImpls { } public final class space/kscience/kmath/nd/Structure2DKt { + public static final fun as2D (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructure2D; public static final fun as2D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure2D; } @@ -2582,3 +2608,462 @@ public final class space/kscience/kmath/structures/VirtualBuffer : space/kscienc public fun iterator ()Ljava/util/Iterator; } +public abstract interface class space/kscience/kmath/tensors/AnalyticTensorAlgebra : space/kscience/kmath/tensors/OrderedTensorAlgebra, space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { + public abstract fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun acosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun asin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun asinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun atan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun atanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun ceil (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun clamp (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun erf (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun erfc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun erfinv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun exp (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun floor (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun heaviside (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun histc (Lspace/kscience/kmath/nd/MutableStructureND;ILjava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun igamma (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun igammac (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun lerp (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun lgamma (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun log (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun logit (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun mvlgamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun polygamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun pow (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun quantile (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun round (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun sigmoid (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun sin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun sinc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun sinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun sqrt (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun std (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun tan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun tanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun trapz (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; +} + +public abstract interface class space/kscience/kmath/tensors/ComplexTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { + public abstract fun angle (Lspace/kscience/kmath/tensors/ComplexTensorStructure;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun bartlettWindow (IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun blackmanWindow (IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cartesianEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/tensors/ComplexTensorStructure; + public abstract fun hammingWindow (IZLjava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun inverseShortTimeFourierTransform (Lspace/kscience/kmath/tensors/ComplexTensorStructure;IIILspace/kscience/kmath/nd/MutableStructureND;ZZZI)V + public abstract fun kaiserWindow (IZLjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun polarEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/tensors/ComplexTensorStructure; + public abstract fun shortTimeFourierTransform (Lspace/kscience/kmath/tensors/ComplexTensorStructure;IIILspace/kscience/kmath/nd/MutableStructureND;ZZ)V + public abstract fun viewAsComplex (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/tensors/ComplexTensorStructure; +} + +public abstract interface class space/kscience/kmath/tensors/ComplexTensorStructure : space/kscience/kmath/nd/MutableStructureND { + public abstract fun imaginaryPart ()Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun realPart ()Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun viewAsReal ()Lspace/kscience/kmath/nd/MutableStructureND; +} + +public final class space/kscience/kmath/tensors/ComplexTensorStructure$DefaultImpls { + public static fun getDimension (Lspace/kscience/kmath/tensors/ComplexTensorStructure;)I +} + +public abstract interface class space/kscience/kmath/tensors/LinearOpsTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { + public abstract fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun lu (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lkotlin/Pair; + public abstract fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; + public abstract fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; + public abstract fun symEig (Lspace/kscience/kmath/nd/MutableStructureND;Z)Lkotlin/Pair; +} + +public final class space/kscience/kmath/tensors/LinearOpsTensorAlgebra$DefaultImpls { + public static synthetic fun symEig$default (Lspace/kscience/kmath/tensors/LinearOpsTensorAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;ZILjava/lang/Object;)Lkotlin/Pair; +} + +public abstract interface class space/kscience/kmath/tensors/OrderedTensorAlgebra : space/kscience/kmath/tensors/TensorAlgebra { + public abstract fun cummax (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cummin (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun max (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun maximum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public abstract fun median (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun min (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun minimum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public abstract fun sort (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; +} + +public abstract interface class space/kscience/kmath/tensors/ReduceOpsTensorAlgebra : space/kscience/kmath/tensors/TensorAlgebra { + public abstract fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; +} + +public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { + public abstract fun abs (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cat (Ljava/util/List;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cumprod (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun flatten (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun fullLike (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public abstract fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public abstract fun ones ([I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun onesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public abstract fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public abstract fun prod (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun square (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun squeeze (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun sum (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun times (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public abstract fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public abstract fun transpose (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun zeroesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun zeros ([I)Lspace/kscience/kmath/nd/MutableStructureND; +} + +public final class space/kscience/kmath/tensors/TensorAlgebra$DefaultImpls { + public static synthetic fun diagonalEmbedding$default (Lspace/kscience/kmath/tensors/TensorAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;IIIILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; +} + +public abstract interface class space/kscience/kmath/tensors/TensorPartialDivisionAlgebra : space/kscience/kmath/tensors/TensorAlgebra { + public abstract fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public abstract fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public abstract fun mean (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun variance (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; +} + +public final class space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra { + public fun ()V + public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun div (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun minus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun plus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun times (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun timesAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V +} + +public final class space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebraKt { + public static final fun BroadcastDoubleTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public class space/kscience/kmath/tensors/core/BufferedTensor : space/kscience/kmath/nd/MutableStructureND { + public fun ([ILspace/kscience/kmath/structures/MutableBuffer;I)V + public fun elements ()Lkotlin/sequences/Sequence; + public fun equals (Ljava/lang/Object;)Z + public final fun forEachMatrix (Lkotlin/jvm/functions/Function1;)V + public final fun forEachVector (Lkotlin/jvm/functions/Function1;)V + public fun get ([I)Ljava/lang/Object; + public final fun getBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun getDimension ()I + public final fun getLinearStructure ()Lspace/kscience/kmath/tensors/core/TensorLinearStructure; + public final fun getNumel ()I + public fun getShape ()[I + public fun hashCode ()I + public final fun matrixSequence ()Lkotlin/sequences/Sequence; + public fun set ([ILjava/lang/Object;)V + public final fun vectorSequence ()Lkotlin/sequences/Sequence; +} + +public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra : space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra, space/kscience/kmath/tensors/AnalyticTensorAlgebra { + public fun ()V + public synthetic fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun acos (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun acosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun acosh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun asin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun asin (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun asinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun asinh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun atan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun atan (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun atanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun atanh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun ceil (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun ceil (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun clamp (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun clamp (Lspace/kscience/kmath/tensors/core/DoubleTensor;DD)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun cos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cos (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun cosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cosh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun erf (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun erf (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun erfc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun erfc (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun erfinv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun erfinv (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun exp (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun exp (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun floor (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun floor (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun heaviside (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun heaviside (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun histc (Lspace/kscience/kmath/nd/MutableStructureND;ILjava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun histc (Lspace/kscience/kmath/tensors/core/DoubleTensor;IDD)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun igamma (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun igamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun igammac (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun igammac (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun lerp (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun lerp (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun lgamma (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun lgamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun log (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun log (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun logit (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun logit (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun mvlgamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun mvlgamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun polygamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun polygamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun pow (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun pow (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun quantile (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun quantile (Lspace/kscience/kmath/tensors/core/DoubleTensor;DIZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun round (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun round (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun sigmoid (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sigmoid (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun sin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sin (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun sinc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sinc (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun sinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sinh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun sqrt (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sqrt (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun std (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun std (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun tan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun tan (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun tanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun tanh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun trapz (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun trapz (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; +} + +public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebraKt { + public static final fun DoubleAnalyticTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/LinearOpsTensorAlgebra { + public fun ()V + public synthetic fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cholesky (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun inv (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun lu (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lkotlin/Pair; + public fun lu (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lkotlin/Pair; + public synthetic fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; + public fun luPivot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/IntTensor;)Lkotlin/Triple; + public synthetic fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun qr (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; + public fun svd (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Triple; + public synthetic fun symEig (Lspace/kscience/kmath/nd/MutableStructureND;Z)Lkotlin/Pair; + public fun symEig (Lspace/kscience/kmath/tensors/core/DoubleTensor;Z)Lkotlin/Pair; +} + +public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebraKt { + public static final fun DoubleLinearOpsTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public class space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/OrderedTensorAlgebra { + public fun ()V + public synthetic fun cummax (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cummax (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun cummin (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cummin (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun max (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun max (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun maximum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun maximum (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun median (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun median (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun min (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun min (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun minimum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun minimum (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun sort (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sort (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; +} + +public final class space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebraKt { + public static final fun DoubleOrderedTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/ReduceOpsTensorAlgebra { + public fun ()V + public synthetic fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; + public fun value (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Ljava/lang/Double; +} + +public final class space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebraKt { + public static final fun DoubleReduceOpsTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/tensors/core/DoubleTensor : space/kscience/kmath/tensors/core/BufferedTensor { +} + +public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { + public fun ()V + public synthetic fun abs (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun abs (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun cat (Ljava/util/List;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cat (Ljava/util/List;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z + public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z + public static synthetic fun contentEquals$default (Lspace/kscience/kmath/tensors/core/DoubleTensorAlgebra;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;DILjava/lang/Object;)Z + public synthetic fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun copy (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun cumprod (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cumprod (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun cumsum (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun det (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; + public fun diagonalEmbedding (Lspace/kscience/kmath/tensors/core/DoubleTensor;III)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun div (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun div (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public synthetic fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V + public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun dot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z + public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z + public static synthetic fun eq$default (Lspace/kscience/kmath/tensors/core/DoubleTensorAlgebra;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;DILjava/lang/Object;)Z + public synthetic fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun flatten (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; + public fun flatten (Lspace/kscience/kmath/tensors/core/DoubleTensor;II)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun fromArray ([I[D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun full (D[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun fullLike (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun fullLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun get (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun map (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun mean (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun mean (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun minus (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun minus (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun minus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V + public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun ones ([I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun ones ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun onesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun onesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun plus (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun plus (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun plus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V + public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun prod (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun prod (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun square (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun square (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun squeeze (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun squeeze (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun sum (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun sum (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun times (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun times (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public fun times (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V + public synthetic fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V + public fun timesAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V + public fun timesAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V + public synthetic fun transpose (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; + public fun transpose (Lspace/kscience/kmath/tensors/core/DoubleTensor;II)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun unaryMinus (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun variance (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; + public fun variance (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun view (Lspace/kscience/kmath/tensors/core/DoubleTensor;[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun viewAs (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun zeroesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun zeroesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun zeros ([I)Lspace/kscience/kmath/nd/MutableStructureND; + public fun zeros ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; +} + +public final class space/kscience/kmath/tensors/core/DoubleTensorAlgebraKt { + public static final fun DoubleTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/tensors/core/FloatTensor : space/kscience/kmath/tensors/core/BufferedTensor { +} + +public final class space/kscience/kmath/tensors/core/IntTensor : space/kscience/kmath/tensors/core/BufferedTensor { +} + +public final class space/kscience/kmath/tensors/core/LongTensor : space/kscience/kmath/tensors/core/BufferedTensor { +} + +public final class space/kscience/kmath/tensors/core/TensorLinearStructure { + public fun ([I)V + public final fun getShape ()[I + public final fun getSize ()I + public final fun getStrides ()[I + public final fun index (I)[I + public final fun indices ()Lkotlin/sequences/Sequence; + public final fun offset ([I)I + public final fun stepIndex ([I)[I +} + diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 8be0dc149..e41b7546c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -3,11 +3,6 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { - public fun TensorType.map(transform: (T) -> T): TensorType - - public fun TensorType.eq(other: TensorType, eqFunction: (T, T) -> Boolean): Boolean - public fun TensorType.contentEquals(other: TensorType, eqFunction: (T, T) -> Boolean): Boolean - //https://pytorch.org/docs/stable/generated/torch.full.html public fun full(value: T, shape: IntArray): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 57339adfa..67b50970b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -277,7 +277,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Double): DoubleTensor { + public fun DoubleTensor.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( this.shape, this.buffer.array().map { transform(it) }.toDoubleArray(), @@ -293,17 +293,17 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra abs(x - y) < delta } } - override fun DoubleTensor.contentEquals(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { + public fun DoubleTensor.contentEquals(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { if (!(this.shape contentEquals other.shape)){ return false } return this.eq(other, eqFunction) } - override fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { + public fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { // todo broadcasting checking - val n = this.strides.linearSize - if (n != other.strides.linearSize){ + val n = this.linearStructure.size + if (n != other.linearStructure.size){ return false } for (i in 0 until n){ From 67aa173927c3f50dcea398d201236c54ad5fe4e0 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 22 Mar 2021 16:11:54 +0700 Subject: [PATCH 124/393] Some documentation updates --- .../kscience/kmath/domains/DoubleDomain.kt | 1 - .../kscience/kmath/linear/LinearSolver.kt | 14 ++++++-- .../kscience/kmath/linear/LinearSpace.kt | 2 ++ .../kscience/kmath/operations/Algebra.kt | 19 +++++----- .../space/kscience/kmath/operations/BigInt.kt | 7 ++-- .../kscience/kmath/functions/Piecewise.kt | 35 +++++++++++++++---- .../kscience/kmath/functions/Polynomial.kt | 3 ++ 7 files changed, 61 insertions(+), 20 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt index 057a4a344..154763159 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt @@ -24,7 +24,6 @@ import space.kscience.kmath.misc.UnstableKMathAPI */ @UnstableKMathAPI public interface DoubleDomain : Domain { - /** * Global lower edge * @param num axis number diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt index af136c552..3e2dbee3f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt @@ -3,7 +3,10 @@ package space.kscience.kmath.linear import space.kscience.kmath.nd.as1D /** - * A group of methods to resolve equation A dot X = B, where A and B are matrices or vectors + * A group of methods to solve for *X* in equation *X = A -1 · B*, where *A* and *B* are matrices or + * vectors. + * + * @param T the type of items. */ public interface LinearSolver { /** @@ -23,7 +26,7 @@ public interface LinearSolver { } /** - * Convert matrix to vector if it is possible + * Convert matrix to vector if it is possible. */ public fun Matrix.asVector(): Point = if (this.colNum == 1) @@ -31,4 +34,11 @@ public fun Matrix.asVector(): Point = else error("Can't convert matrix with more than one column to vector") +/** + * Creates an n × 1 [VirtualMatrix], where n is the size of the given buffer. + * + * @param T the type of elements contained in the buffer. + * @receiver a buffer. + * @return the new matrix. + */ public fun Point.asMatrix(): VirtualMatrix = VirtualMatrix(size, 1) { i, _ -> get(i) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 6a587270b..921f4c79c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -17,6 +17,8 @@ public typealias Matrix = Structure2D /** * Alias or using [Buffer] as a point/vector in a many-dimensional space. + * + * @param T the type of elements contained in the buffer. */ public typealias Point = Buffer diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 9f57bc4c1..960b7581c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -100,8 +100,8 @@ public fun Algebra.bindSymbol(symbol: Symbol): T = bindSymbol(symbo public inline operator fun
, R> A.invoke(block: A.() -> R): R = run(block) /** - * Represents linear space without neutral element, i.e. algebraic structure with associative, binary operation [add] - * and scalar multiplication [multiply]. + * Represents group without neutral element (also known as inverse semigroup), i.e. algebraic structure with + * associative, binary operation [add]. * * @param T the type of element of this semispace. */ @@ -177,7 +177,7 @@ public interface GroupOperations : Algebra { } /** - * Represents linear space with neutral element, i.e. algebraic structure with associative, binary operation [add]. + * Represents group, i.e. algebraic structure with associative, binary operation [add]. * * @param T the type of element of this semispace. */ @@ -189,8 +189,8 @@ public interface Group : GroupOperations { } /** - * Represents rng, i.e. algebraic structure with associative, binary, commutative operation [add] and associative, - * operation [multiply] distributive over [add]. + * Represents ring without multiplicative and additive identities, i.e. algebraic structure with + * associative, binary, commutative operation [add] and associative, operation [multiply] distributive over [add]. * * @param T the type of element of this semiring. */ @@ -238,7 +238,7 @@ public interface Ring : Group, RingOperations { } /** - * Represents field without identity elements, i.e. algebraic structure with associative, binary, commutative operations + * Represents field without without multiplicative and additive identities, i.e. algebraic structure with associative, binary, commutative operations * [add] and [multiply]; binary operation [divide] as multiplication of left operand by reciprocal of right one. * * @param T the type of element of this semifield. @@ -276,10 +276,11 @@ public interface FieldOperations : RingOperations { } /** - * Represents field, i.e. algebraic structure with three operations: associative "addition" and "multiplication", - * and "division" and their neutral elements. + * Represents field, i.e. algebraic structure with three operations: associative, commutative addition and + * multiplication, and division. **This interface differs from the eponymous mathematical definition: fields in KMath + * also support associative multiplication by scalar.** * - * @param T the type of element of this semifield. + * @param T the type of element of this field. */ public interface Field : Ring, FieldOperations, ScaleOperations, NumericAlgebra { override fun number(value: Number): T = scale(one, value.toDouble()) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 55bb68850..b5e27575b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -12,8 +12,8 @@ import kotlin.math.max import kotlin.math.min import kotlin.math.sign -public typealias Magnitude = UIntArray -public typealias TBase = ULong +private typealias Magnitude = UIntArray +private typealias TBase = ULong /** * Kotlin Multiplatform implementation of Big Integer numbers (KBigInteger). @@ -358,6 +358,9 @@ private fun stripLeadingZeros(mag: Magnitude): Magnitude { return mag.sliceArray(IntRange(0, resSize)) } +/** + * Returns the absolute value of the given value [x]. + */ public fun abs(x: BigInt): BigInt = x.abs() /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index d2470a4b4..3510973be 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -2,14 +2,28 @@ package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring +/** + * Represents piecewise-defined function. + * + * @param T the piece key type. + * @param R the sub-function type. + */ public fun interface Piecewise { + /** + * Returns the appropriate sub-function for given piece key. + */ public fun findPiece(arg: T): R? } +/** + * Represents piecewise-defined function where all the sub-functions are polynomials. + */ public fun interface PiecewisePolynomial : Piecewise> /** - * Ordered list of pieces in piecewise function + * Basic [Piecewise] implementation where all the pieces are ordered by the [Comparable] type instances. + * + * @param T the comparable piece key type. */ public class OrderedPiecewisePolynomial>(delimiter: T) : PiecewisePolynomial { @@ -17,8 +31,10 @@ public class OrderedPiecewisePolynomial>(delimiter: T) : private val pieces: MutableList> = arrayListOf() /** - * Dynamically add a piece to the "right" side (beyond maximum argument value of previous piece) - * @param right new rightmost position. If is less then current rightmost position, a error is thrown. + * Dynamically adds a piece to the right side (beyond maximum argument value of previous piece) + * + * @param right new rightmost position. If is less then current rightmost position, an error is thrown. + * @param piece the sub-function. */ public fun putRight(right: T, piece: Polynomial) { require(right > delimiters.last()) { "New delimiter should be to the right of old one" } @@ -26,13 +42,19 @@ public class OrderedPiecewisePolynomial>(delimiter: T) : pieces.add(piece) } + /** + * Dynamically adds a piece to the left side (beyond maximum argument value of previous piece) + * + * @param left the new leftmost position. If is less then current rightmost position, an error is thrown. + * @param piece the sub-function. + */ public fun putLeft(left: T, piece: Polynomial) { require(left < delimiters.first()) { "New delimiter should be to the left of old one" } delimiters.add(0, left) pieces.add(0, piece) } - override fun findPiece(arg: T): Polynomial? { + public override fun findPiece(arg: T): Polynomial? { if (arg < delimiters.first() || arg >= delimiters.last()) return null else { @@ -46,9 +68,10 @@ public class OrderedPiecewisePolynomial>(delimiter: T) : } /** - * Return a value of polynomial function with given [ring] an given [arg] or null if argument is outside of piecewise definition. + * Return a value of polynomial function with given [ring] an given [arg] or null if argument is outside of piecewise + * definition. */ public fun , C : Ring> PiecewisePolynomial.value(ring: C, arg: T): T? = findPiece(arg)?.value(ring, arg) -public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { value(ring, it) } \ No newline at end of file +public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { value(ring, it) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 049909fe1..9f4e21991 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -15,6 +15,9 @@ import kotlin.math.pow */ public inline class Polynomial(public val coefficients: List) +/** + * Returns a [Polynomial] instance with given [coefficients]. + */ @Suppress("FunctionName") public fun Polynomial(vararg coefficients: T): Polynomial = Polynomial(coefficients.toList()) From 1b01654667877eff08b5ffe0fb83fc6458cae238 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 22 Mar 2021 18:32:08 +0700 Subject: [PATCH 125/393] Improve Dokka configuration --- README.md | 11 +++-- build.gradle.kts | 24 ++++++++- docs/templates/ARTIFACT-TEMPLATE.md | 62 +++++++++++------------ docs/templates/README-TEMPLATE.md | 5 +- gradle.properties | 2 +- kmath-ast/README.md | 66 +++++++++++-------------- kmath-ast/docs/README-TEMPLATE.md | 4 +- kmath-complex/README.md | 66 +++++++++++-------------- kmath-complex/docs/README-TEMPLATE.md | 4 +- kmath-core/README.md | 66 +++++++++++-------------- kmath-core/docs/README-TEMPLATE.md | 4 +- kmath-ejml/README.md | 66 +++++++++++-------------- kmath-ejml/docs/README-TEMPLATE.md | 4 +- kmath-for-real/README.md | 66 ++++++++++++------------- kmath-for-real/docs/README-TEMPLATE.md | 4 +- kmath-functions/README.md | 66 +++++++++++-------------- kmath-functions/docs/README-TEMPLATE.md | 4 +- kmath-nd4j/README.md | 66 +++++++++++-------------- kmath-nd4j/docs/README-TEMPLATE.md | 4 +- 19 files changed, 288 insertions(+), 306 deletions(-) diff --git a/README.md b/README.md index cc9439d27..7080c757e 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ [![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) - ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) - -[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22%20AND%20a:%22kmath-core%22) +[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22) +[![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fkscience%2Fkmath%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) # KMath @@ -147,6 +146,12 @@ performance calculations to code generation. > > > **Maturity**: PROTOTYPE +> +> **Features:** +> - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix. +> - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix. +> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix. +
* ### [kmath-for-real](kmath-for-real) diff --git a/build.gradle.kts b/build.gradle.kts index 5f1a8b88a..67cb2a2fc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,6 @@ +import org.jetbrains.dokka.gradle.DokkaTask import ru.mipt.npm.gradle.KSciencePublishingPlugin +import java.net.URL plugins { id("ru.mipt.npm.gradle.project") @@ -9,7 +11,6 @@ allprojects { jcenter() maven("https://clojars.org/repo") maven("https://dl.bintray.com/egor-bogomolov/astminer/") - maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/mipt-npm/dev") @@ -25,6 +26,27 @@ allprojects { subprojects { if (name.startsWith("kmath")) apply() + + afterEvaluate { + tasks.withType { + dokkaSourceSets.all { + val readmeFile = File(this@subprojects.projectDir, "./README.md") + if (readmeFile.exists()) + includes.setFrom(includes + readmeFile.absolutePath) + + arrayOf( + "http://ejml.org/javadoc/", + "https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/", + "https://deeplearning4j.org/api/latest/" + ).map { URL("${it}package-list") to URL(it) }.forEach { (a, b) -> + externalDocumentationLink { + packageListUrl.set(a) + url.set(b) + } + } + } + } + } } readme { diff --git a/docs/templates/ARTIFACT-TEMPLATE.md b/docs/templates/ARTIFACT-TEMPLATE.md index cb741bc6f..01d9c51da 100644 --- a/docs/templates/ARTIFACT-TEMPLATE.md +++ b/docs/templates/ARTIFACT-TEMPLATE.md @@ -1,34 +1,28 @@ -> #### Artifact: -> -> This module artifact: `${group}:${name}:${version}`. -> -> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/${name}/images/download.svg) ](https://bintray.com/mipt-npm/kscience/${name}/_latestVersion) -> -> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/${name}/images/download.svg) ](https://bintray.com/mipt-npm/dev/${name}/_latestVersion) -> -> **Gradle:** -> -> ```gradle -> repositories { -> maven { url 'https://repo.kotlin.link' } -> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } -> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap -> } -> -> dependencies { -> implementation '${group}:${name}:${version}' -> } -> ``` -> **Gradle Kotlin DSL:** -> -> ```kotlin -> repositories { -> maven("https://repo.kotlin.link") -> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap -> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a -> } -> -> dependencies { -> implementation("${group}:${name}:${version}") -> } -> ``` \ No newline at end of file +## Artifact: + +The Maven coordinates of this project are `${group}:${name}:${version}`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap +} + +dependencies { + implementation '${group}:${name}:${version}' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + maven("https://dl.bintray.com/hotkeytlt/maven") // required for a +} + +dependencies { + implementation("${group}:${name}:${version}") +} +``` \ No newline at end of file diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index 4366c8fcd..3502cdccd 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -1,9 +1,8 @@ [![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) - ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) - -[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22%20AND%20a:%22kmath-core%22) +[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22) +[![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fkscience%2Fkmath%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) # KMath diff --git a/gradle.properties b/gradle.properties index 7ff50a435..50123b16c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,5 +4,5 @@ kotlin.mpp.stability.nowarn=true kotlin.native.enableDependencyPropagation=false kotlin.parallel.tasks.in.project=true org.gradle.configureondemand=true -org.gradle.jvmargs=-XX:MaxMetaspaceSize=2G +org.gradle.jvmargs=-XX:MaxMetaspaceSize=9G org.gradle.parallel=true diff --git a/kmath-ast/README.md b/kmath-ast/README.md index ee14604d2..ff954b914 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -1,6 +1,6 @@ -# Abstract Syntax Tree Expression Representation and Operations (`kmath-ast`) +# Module kmath-ast -This subproject implements the following features: +Abstract syntax tree expression representation and related optimizations. - [expression-language](src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser - [mst](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation @@ -10,40 +10,34 @@ This subproject implements the following features: - [mst-js-codegen](src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler -> #### Artifact: -> -> This module artifact: `space.kscience:kmath-ast:0.3.0-dev-3`. -> -> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-ast/_latestVersion) -> -> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-ast/_latestVersion) -> -> **Gradle:** -> -> ```gradle -> repositories { -> maven { url 'https://repo.kotlin.link' } -> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } -> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap -> } -> -> dependencies { -> implementation 'space.kscience:kmath-ast:0.3.0-dev-3' -> } -> ``` -> **Gradle Kotlin DSL:** -> -> ```kotlin -> repositories { -> maven("https://repo.kotlin.link") -> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap -> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a -> } -> -> dependencies { -> implementation("space.kscience:kmath-ast:0.3.0-dev-3") -> } -> ``` +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-3`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap +} + +dependencies { + implementation 'space.kscience:kmath-ast:0.3.0-dev-3' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + maven("https://dl.bintray.com/hotkeytlt/maven") // required for a +} + +dependencies { + implementation("space.kscience:kmath-ast:0.3.0-dev-3") +} +``` ## Dynamic expression code generation diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index 80e48008b..db071adb4 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -1,6 +1,6 @@ -# Abstract Syntax Tree Expression Representation and Operations (`kmath-ast`) +# Module kmath-ast -This subproject implements the following features: +Abstract syntax tree expression representation and related optimizations. ${features} diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 9e9cd5b6f..d7b2937fd 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -1,42 +1,36 @@ -# The Core Module (`kmath-core`) +# Module kmath-complex -Complex and hypercomplex number systems in KMath: +Complex and hypercomplex number systems in KMath. - [complex](src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers - [quaternion](src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions -> #### Artifact: -> -> This module artifact: `space.kscience:kmath-complex:0.3.0-dev-3`. -> -> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-complex/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-complex/_latestVersion) -> -> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-complex/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-complex/_latestVersion) -> -> **Gradle:** -> -> ```gradle -> repositories { -> maven { url 'https://repo.kotlin.link' } -> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } -> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap -> } -> -> dependencies { -> implementation 'space.kscience:kmath-complex:0.3.0-dev-3' -> } -> ``` -> **Gradle Kotlin DSL:** -> -> ```kotlin -> repositories { -> maven("https://repo.kotlin.link") -> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap -> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a -> } -> -> dependencies { -> implementation("space.kscience:kmath-complex:0.3.0-dev-3") -> } -> ``` +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-3`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap +} + +dependencies { + implementation 'space.kscience:kmath-complex:0.3.0-dev-3' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + maven("https://dl.bintray.com/hotkeytlt/maven") // required for a +} + +dependencies { + implementation("space.kscience:kmath-complex:0.3.0-dev-3") +} +``` diff --git a/kmath-complex/docs/README-TEMPLATE.md b/kmath-complex/docs/README-TEMPLATE.md index 462fd617e..106d4aff1 100644 --- a/kmath-complex/docs/README-TEMPLATE.md +++ b/kmath-complex/docs/README-TEMPLATE.md @@ -1,6 +1,6 @@ -# The Core Module (`kmath-core`) +# Module kmath-complex -Complex and hypercomplex number systems in KMath: +Complex and hypercomplex number systems in KMath. ${features} diff --git a/kmath-core/README.md b/kmath-core/README.md index 4e4b5273d..096c7d833 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -1,6 +1,6 @@ -# The Core Module (`kmath-core`) +# Module kmath-core -The core features of KMath: +The core interfaces of KMath. - [algebras](src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields. - [nd](src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt) : Many-dimensional structures and operations on them. @@ -13,37 +13,31 @@ performance calculations to code generation. - [autodif](src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation -> #### Artifact: -> -> This module artifact: `space.kscience:kmath-core:0.3.0-dev-3`. -> -> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) -> -> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion) -> -> **Gradle:** -> -> ```gradle -> repositories { -> maven { url 'https://repo.kotlin.link' } -> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } -> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap -> } -> -> dependencies { -> implementation 'space.kscience:kmath-core:0.3.0-dev-3' -> } -> ``` -> **Gradle Kotlin DSL:** -> -> ```kotlin -> repositories { -> maven("https://repo.kotlin.link") -> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap -> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a -> } -> -> dependencies { -> implementation("space.kscience:kmath-core:0.3.0-dev-3") -> } -> ``` +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-3`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap +} + +dependencies { + implementation 'space.kscience:kmath-core:0.3.0-dev-3' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + maven("https://dl.bintray.com/hotkeytlt/maven") // required for a +} + +dependencies { + implementation("space.kscience:kmath-core:0.3.0-dev-3") +} +``` diff --git a/kmath-core/docs/README-TEMPLATE.md b/kmath-core/docs/README-TEMPLATE.md index 83d1ebdce..41cfe1ccb 100644 --- a/kmath-core/docs/README-TEMPLATE.md +++ b/kmath-core/docs/README-TEMPLATE.md @@ -1,6 +1,6 @@ -# The Core Module (`kmath-core`) +# Module kmath-core -The core features of KMath: +The core interfaces of KMath. ${features} diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index 1081b2b7f..2551703a4 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -1,43 +1,37 @@ -# ejml-simple support (`kmath-ejml`) +# Module kmath-ejml -This subproject implements the following features: +EJML based linear algebra implementation. - [ejml-vector](src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix. - [ejml-matrix](src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix. - [ejml-linear-space](src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix. -> #### Artifact: -> -> This module artifact: `space.kscience:kmath-ejml:0.3.0-dev-3`. -> -> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-ejml/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-ejml/_latestVersion) -> -> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-ejml/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-ejml/_latestVersion) -> -> **Gradle:** -> -> ```gradle -> repositories { -> maven { url 'https://repo.kotlin.link' } -> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } -> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap -> } -> -> dependencies { -> implementation 'space.kscience:kmath-ejml:0.3.0-dev-3' -> } -> ``` -> **Gradle Kotlin DSL:** -> -> ```kotlin -> repositories { -> maven("https://repo.kotlin.link") -> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap -> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a -> } -> -> dependencies { -> implementation("space.kscience:kmath-ejml:0.3.0-dev-3") -> } -> ``` +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-3`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap +} + +dependencies { + implementation 'space.kscience:kmath-ejml:0.3.0-dev-3' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + maven("https://dl.bintray.com/hotkeytlt/maven") // required for a +} + +dependencies { + implementation("space.kscience:kmath-ejml:0.3.0-dev-3") +} +``` diff --git a/kmath-ejml/docs/README-TEMPLATE.md b/kmath-ejml/docs/README-TEMPLATE.md index c53f4a81c..27fcedd65 100644 --- a/kmath-ejml/docs/README-TEMPLATE.md +++ b/kmath-ejml/docs/README-TEMPLATE.md @@ -1,6 +1,6 @@ -# ejml-simple support (`kmath-ejml`) +# Module kmath-ejml -This subproject implements the following features: +EJML based linear algebra implementation. ${features} diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 139cd3cef..ad3d33062 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -1,41 +1,37 @@ -# Real number specialization module (`kmath-for-real`) +# Module kmath-for-real + +Specialization of KMath APIs for Double numbers. - [DoubleVector](src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt) : Numpy-like operations for Buffers/Points - [DoubleMatrix](src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt) : Numpy-like operations for 2d real structures - [grids](src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt) : Uniform grid generators -> #### Artifact: -> -> This module artifact: `space.kscience:kmath-for-real:0.3.0-dev-3`. -> -> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-for-real/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-for-real/_latestVersion) -> -> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-for-real/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-for-real/_latestVersion) -> -> **Gradle:** -> -> ```gradle -> repositories { -> maven { url 'https://repo.kotlin.link' } -> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } -> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap -> } -> -> dependencies { -> implementation 'space.kscience:kmath-for-real:0.3.0-dev-3' -> } -> ``` -> **Gradle Kotlin DSL:** -> -> ```kotlin -> repositories { -> maven("https://repo.kotlin.link") -> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap -> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a -> } -> -> dependencies { -> implementation("space.kscience:kmath-for-real:0.3.0-dev-3") -> } -> ``` +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-3`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap +} + +dependencies { + implementation 'space.kscience:kmath-for-real:0.3.0-dev-3' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + maven("https://dl.bintray.com/hotkeytlt/maven") // required for a +} + +dependencies { + implementation("space.kscience:kmath-for-real:0.3.0-dev-3") +} +``` diff --git a/kmath-for-real/docs/README-TEMPLATE.md b/kmath-for-real/docs/README-TEMPLATE.md index 670844bd0..c2ef25aa7 100644 --- a/kmath-for-real/docs/README-TEMPLATE.md +++ b/kmath-for-real/docs/README-TEMPLATE.md @@ -1,4 +1,6 @@ -# Real number specialization module (`kmath-for-real`) +# Module kmath-for-real + +Specialization of KMath APIs for Double numbers. ${features} diff --git a/kmath-functions/README.md b/kmath-functions/README.md index d13c4c107..531e97a44 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -1,6 +1,6 @@ -# Functions (`kmath-functions`) +# Module kmath-functions -Functions and interpolations: +Functions and interpolations. - [piecewise](Piecewise functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt - [polynomials](Polynomial functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -8,37 +8,31 @@ Functions and interpolations: - [spline interpolation](Cubic spline XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt -> #### Artifact: -> -> This module artifact: `space.kscience:kmath-functions:0.3.0-dev-3`. -> -> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-functions/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-functions/_latestVersion) -> -> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-functions/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-functions/_latestVersion) -> -> **Gradle:** -> -> ```gradle -> repositories { -> maven { url 'https://repo.kotlin.link' } -> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } -> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap -> } -> -> dependencies { -> implementation 'space.kscience:kmath-functions:0.3.0-dev-3' -> } -> ``` -> **Gradle Kotlin DSL:** -> -> ```kotlin -> repositories { -> maven("https://repo.kotlin.link") -> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap -> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a -> } -> -> dependencies { -> implementation("space.kscience:kmath-functions:0.3.0-dev-3") -> } -> ``` +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-3`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap +} + +dependencies { + implementation 'space.kscience:kmath-functions:0.3.0-dev-3' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + maven("https://dl.bintray.com/hotkeytlt/maven") // required for a +} + +dependencies { + implementation("space.kscience:kmath-functions:0.3.0-dev-3") +} +``` diff --git a/kmath-functions/docs/README-TEMPLATE.md b/kmath-functions/docs/README-TEMPLATE.md index 8a34a7cc4..2e163eee5 100644 --- a/kmath-functions/docs/README-TEMPLATE.md +++ b/kmath-functions/docs/README-TEMPLATE.md @@ -1,6 +1,6 @@ -# Functions (`kmath-functions`) +# Module kmath-functions -Functions and interpolations: +Functions and interpolations. ${features} diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 2771722eb..938d05c33 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -1,46 +1,40 @@ -# ND4J NDStructure implementation (`kmath-nd4j`) +# Module kmath-nd4j -This subproject implements the following features: +ND4J based implementations of KMath abstractions. - [nd4jarraystructure](#) : NDStructure wrapper for INDArray - [nd4jarrayrings](#) : Rings over Nd4jArrayStructure of Int and Long - [nd4jarrayfields](#) : Fields over Nd4jArrayStructure of Float and Double -> #### Artifact: -> -> This module artifact: `space.kscience:kmath-nd4j:0.3.0-dev-3`. -> -> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-nd4j/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-nd4j/_latestVersion) -> -> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-nd4j/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-nd4j/_latestVersion) -> -> **Gradle:** -> -> ```gradle -> repositories { -> maven { url 'https://repo.kotlin.link' } -> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } -> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap -> } -> -> dependencies { -> implementation 'space.kscience:kmath-nd4j:0.3.0-dev-3' -> } -> ``` -> **Gradle Kotlin DSL:** -> -> ```kotlin -> repositories { -> maven("https://repo.kotlin.link") -> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap -> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a -> } -> -> dependencies { -> implementation("space.kscience:kmath-nd4j:0.3.0-dev-3") -> } -> ``` +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-3`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap +} + +dependencies { + implementation 'space.kscience:kmath-nd4j:0.3.0-dev-3' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + maven("https://dl.bintray.com/hotkeytlt/maven") // required for a +} + +dependencies { + implementation("space.kscience:kmath-nd4j:0.3.0-dev-3") +} +``` ## Examples diff --git a/kmath-nd4j/docs/README-TEMPLATE.md b/kmath-nd4j/docs/README-TEMPLATE.md index 9783e74be..5f325cab5 100644 --- a/kmath-nd4j/docs/README-TEMPLATE.md +++ b/kmath-nd4j/docs/README-TEMPLATE.md @@ -1,6 +1,6 @@ -# ND4J NDStructure implementation (`kmath-nd4j`) +# Module kmath-nd4j -This subproject implements the following features: +ND4J based implementations of KMath abstractions. ${features} From 2d2c4bd4744af9f3d841571d213170b1d661fa8f Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Tue, 23 Mar 2021 14:53:54 +0300 Subject: [PATCH 126/393] add broadcast of all dims except the last 2, add tensors dot, fix bug in function times --- .../core/BroadcastDoubleTensorAlgebra.kt | 59 +++++++++++++- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 80 ++++++++++++++++++- .../kmath/tensors/core/TestBroadcasting.kt | 30 +++++++ .../tensors/core/TestDoubleTensorAlgebra.kt | 14 ++++ 4 files changed, 180 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index 4bfbe5863..425178fc1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -85,7 +85,6 @@ public inline fun BroadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorA internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { - println(shapes) var totalDim = 0 for (shape in shapes) { totalDim = max(totalDim, shape.size) @@ -179,5 +178,63 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List { + var onlyTwoDims = true + for (tensor in tensors) { + if (tensor.shape.size < 2) { + throw RuntimeException("Tensors must have at least 2 dimensions") + } + if (tensor.shape.size != 2) { + onlyTwoDims = false + } + } + + if (onlyTwoDims) { + return tensors.asList() + } + + val totalShape = broadcastShapes(*(tensors.map { it.shape.sliceArray(0..it.shape.size - 3) }).toTypedArray()) + val n = totalShape.reduce { acc, i -> acc * i } + + val res = ArrayList(0) + for (tensor in tensors) { + val matrixShape = tensor.shape.sliceArray(tensor.shape.size - 2 until tensor.shape.size).copyOf() + val matrixSize = matrixShape[0] * matrixShape[1] + val matrix = DoubleTensor(matrixShape, DoubleArray(matrixSize)) + + val outerTensor = DoubleTensor(totalShape, DoubleArray(n)) + val resTensor = DoubleTensor(totalShape + matrixShape, DoubleArray(n * matrixSize)) + + for (linearIndex in 0 until n) { + val totalMultiIndex = outerTensor.linearStructure.index(linearIndex) + var curMultiIndex = tensor.shape.sliceArray(0..tensor.shape.size - 3).copyOf() + curMultiIndex = IntArray(totalMultiIndex.size - curMultiIndex.size) {1} + curMultiIndex + + val newTensor = DoubleTensor(curMultiIndex + matrixShape, tensor.buffer.array()) + + for (i in curMultiIndex.indices) { + if (curMultiIndex[i] != 1) { + curMultiIndex[i] = totalMultiIndex[i] + } else { + curMultiIndex[i] = 0 + } + } + + for (i in 0 until matrixSize) { + val curLinearIndex = newTensor.linearStructure.offset(curMultiIndex + + matrix.linearStructure.index(i)) + val newLinearIndex = resTensor.linearStructure.offset(totalMultiIndex + + matrix.linearStructure.index(i)) + + resTensor.buffer.array()[resTensor.bufferStart + newLinearIndex] = + newTensor.buffer.array()[newTensor.bufferStart + curLinearIndex] + } + } + res.add(resTensor) + } + return res } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 67b50970b..9cdc6c130 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -132,7 +132,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra - this.buffer.array()[other.bufferStart + i] * + this.buffer.array()[this.bufferStart + i] * other.buffer.array()[other.bufferStart + i] } return DoubleTensor(this.shape, resBuffer) @@ -241,8 +241,84 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra 2 || other.shape.size > 2) { + throw RuntimeException("Both tensors must have a maximum of 2 dimensions") + } + + if (this.shape[1] != other.shape[0]) { + throw RuntimeException("Tensors dot operation dimension mismatch: " + + "(${this.shape[0]}, ${this.shape[1]}) x (${other.shape[0]}, ${other.shape[1]})") + } + + val l = this.shape[0] + val m = this.shape[1] + val n = other.shape[1] + + val res = DoubleTensor(intArrayOf(l, n), DoubleArray(l * n)) + + for (i in 0 until l) { + for (j in 0 until n) { + var curr = 0.0 + for (k in 0 until m) { + val ik = this.linearStructure.offset(intArrayOf(i, k)) + val kj = other.linearStructure.offset(intArrayOf(k, j)) + curr += this.buffer.array()[ik] * other.buffer.array()[kj] + } + val linearIndex = res.linearStructure.offset(intArrayOf(i, j)) + res.buffer.array()[linearIndex] = curr + } + } + return res + } + override fun DoubleTensor.dot(other: DoubleTensor): DoubleTensor { - TODO("Alya") + if (this.shape.size == 1 && other.shape.size == 1) { + return DoubleTensor(intArrayOf(1), doubleArrayOf(this.times(other).buffer.array().sum())) + } + + var newThis = this.copy() + var newOther = other.copy() + if (this.shape.size == 1) { + newThis = this.view(intArrayOf(1) + this.shape) + } + if (other.shape.size == 1) { + newOther = other.view(other.shape + intArrayOf(1) ) + } + + val broadcastTensors = broadcastOuterTensors(newThis, newOther) + newThis = broadcastTensors[0] + newOther = broadcastTensors[1] + + val l = newThis.shape[newThis.shape.size - 2] + val m1= newThis.shape[newThis.shape.size - 1] + val m2 = newOther.shape[newOther.shape.size - 2] + val n = newOther.shape[newOther.shape.size - 1] + if (m1 != m2) { + throw RuntimeException("Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)") + } + val m = m1 + + var resShape = newThis.shape.sliceArray(0..(newThis.shape.size - 2)) + intArrayOf(newOther.shape.last()) + val resSize = resShape.reduce { acc, i -> acc * i } + val resTensor = DoubleTensor(resShape, DoubleArray(resSize)) + + for ((res, ab) in resTensor.matrixSequence().zip(newThis.matrixSequence().zip(newOther.matrixSequence()))) { + val a = ab.first + val b = ab.second + + for (i in 0 until l) { + for (j in 0 until n) { + var curr = 0.0 + for (k in 0 until m) { + curr += a[i, k] * b[k, j] + } + res[i, j] = curr + } + } + } + + return resTensor } override fun diagonalEmbedding(diagonalEntries: DoubleTensor, offset: Int, dim1: Int, dim2: Int): DoubleTensor { diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 73e3993a1..41c9b72f7 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -47,6 +47,36 @@ class TestBroadcasting { assertTrue(res[2].buffer.array() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) } + @Test + fun broadcastOuterTensors() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) + + val res = broadcastOuterTensors(tensor1, tensor2, tensor3) + + assertTrue(res[0].shape contentEquals intArrayOf(1, 2, 3)) + assertTrue(res[1].shape contentEquals intArrayOf(1, 1, 3)) + assertTrue(res[2].shape contentEquals intArrayOf(1, 1, 1)) + + assertTrue(res[0].buffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].buffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0)) + assertTrue(res[2].buffer.array() contentEquals doubleArrayOf(500.0)) + } + + @Test + fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) {0.0}) + val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) {0.0}) + val tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0)) + + val res = broadcastOuterTensors(tensor1, tensor2, tensor3) + + assertTrue(res[0].shape contentEquals intArrayOf(4, 2, 5, 3, 2, 3)) + assertTrue(res[1].shape contentEquals intArrayOf(4, 2, 5, 3, 3, 3)) + assertTrue(res[2].shape contentEquals intArrayOf(4, 2, 5, 3, 1, 1)) + } + @Test fun minusTensor() = BroadcastDoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 06aa3ebf7..aa3c14412 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -79,6 +79,20 @@ class TestDoubleTensorAlgebra { assertTrue(expected.buffer.array() contentEquals assignResult.buffer.array()) } + @Test + fun dot() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) + val res12 = tensor1.dot(tensor2) + + assertTrue(res12.buffer.array() contentEquals doubleArrayOf(140.0, 320.0)) + assertTrue(res12.shape contentEquals intArrayOf(2, 1)) + + val tensor4 = fromArray(intArrayOf(10, 3, 4), DoubleArray(10 * 3 * 4) {0.0}) + val tensor5 = fromArray(intArrayOf(10, 4, 5), DoubleArray(10 * 4 * 5) {0.0}) + assertTrue(tensor4.dot(tensor5).shape contentEquals intArrayOf(10, 3, 5)) + } + @Test fun testContentEqual() = DoubleTensorAlgebra { //TODO() From 4d160b81b9620c6ab47e244f727db62355948479 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 23 Mar 2021 19:48:12 +0700 Subject: [PATCH 127/393] Improve KDoc comments for kmath-functions --- .../kscience/kmath/functions/Polynomial.kt | 24 +++++++++++++---- .../kscience/kmath/integration/Integrator.kt | 6 ++--- .../kmath/integration/UnivariateIntegrand.kt | 2 +- .../kmath/interpolation/SplineInterpolator.kt | 7 +++-- .../kmath/interpolation/XYPointSet.kt | 27 +++++++++++++++++++ 5 files changed, 55 insertions(+), 11 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 9f4e21991..550785812 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -10,8 +10,9 @@ import kotlin.math.max import kotlin.math.pow /** - * Polynomial coefficients without fixation on specific context they are applied to - * @param coefficients constant is the leftmost coefficient + * Polynomial coefficients model without fixation on specific context they are applied to. + * + * @param coefficients constant is the leftmost coefficient. */ public inline class Polynomial(public val coefficients: List) @@ -21,8 +22,14 @@ public inline class Polynomial(public val coefficients: List) @Suppress("FunctionName") public fun Polynomial(vararg coefficients: T): Polynomial = Polynomial(coefficients.toList()) +/** + * Evaluates the value of the given double polynomial for given double argument. + */ public fun Polynomial.value(): Double = coefficients.reduceIndexed { index, acc, d -> acc + d.pow(index) } +/** + * Evaluates the value of the given polynomial for given argument. + */ public fun > Polynomial.value(ring: C, arg: T): T = ring { if (coefficients.isEmpty()) return@ring zero var res = coefficients.first() @@ -38,19 +45,23 @@ public fun > Polynomial.value(ring: C, arg: T): T = ring } /** - * Represent the polynomial as a regular context-less function + * Represent the polynomial as a regular context-less function. */ public fun > Polynomial.asFunction(ring: C): (T) -> T = { value(ring, it) } /** - * An algebra for polynomials + * Space of polynomials. + * + * @param T the type of operated polynomials. + * @param C the intersection of [Ring] of [T] and [ScaleOperations] of [T]. + * @param ring the [C] instance. */ public class PolynomialSpace( private val ring: C, ) : Group>, ScaleOperations> where C : Ring, C : ScaleOperations { public override val zero: Polynomial = Polynomial(emptyList()) - override fun Polynomial.unaryMinus(): Polynomial = with(ring) { + override fun Polynomial.unaryMinus(): Polynomial = ring { Polynomial(coefficients.map { -it }) } @@ -67,6 +78,9 @@ public class PolynomialSpace( public override fun scale(a: Polynomial, value: Double): Polynomial = ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) } + /** + * Evaluates the polynomial for the given value [arg]. + */ public operator fun Polynomial.invoke(arg: T): T = value(ring, arg) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt index ebc53ad2e..e421fb680 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt @@ -1,11 +1,11 @@ package space.kscience.kmath.integration /** - * A general interface for all integrators + * A general interface for all integrators. */ public interface Integrator { /** - * Run one integration pass and return a new [Integrand] with a new set of features + * Runs one integration pass and return a new [Integrand] with a new set of features. */ public fun integrate(integrand: I): I -} \ No newline at end of file +} diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index 9389318e8..ca4bbf6b8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -61,4 +61,4 @@ public fun UnivariateIntegrator.integrate( return integrate( UnivariateIntegrand(function, *features.toTypedArray()) ).value ?: error("Unexpected: no value after integration.") -} \ No newline at end of file +} diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index ddbe743f0..ef75a1ef8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -8,8 +8,11 @@ import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.MutableBufferFactory /** - * Generic spline interpolator. Not recommended for performance critical places, use platform-specific and type specific ones. - * Based on https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/SplineInterpolator.java + * Generic spline interpolator. Not recommended for performance critical places, use platform-specific and type + * specific ones. + * + * Based on + * https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/SplineInterpolator.java */ public class SplineInterpolator>( public override val algebra: Field, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt index 1ff7b6351..2b1312c0f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt @@ -3,13 +3,40 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.structures.Buffer +/** + * Pair of associated buffers for X and Y axes values. + * + * @param X the type of X values. + * @param Y the type of Y values. + */ public interface XYPointSet { + /** + * The size of all the involved buffers. + */ public val size: Int + + /** + * The buffer of X values. + */ public val x: Buffer + + /** + * The buffer of Y values. + */ public val y: Buffer } +/** + * Triple of associated buffers for X, Y, and Z axes values. + * + * @param X the type of X values. + * @param Y the type of Y values. + * @param Z the type of Z values. + */ public interface XYZPointSet : XYPointSet { + /** + * The buffer of Z values. + */ public val z: Buffer } From 078686a04660e78b9929d2ed9a3c61f3fa888e62 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Tue, 23 Mar 2021 15:59:55 +0300 Subject: [PATCH 128/393] hotfix sequence --- .../space/kscience/kmath/tensors/core/BufferedTensor.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 4f5e1f9f0..160c61260 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -34,7 +34,8 @@ public open class BufferedTensor( public fun vectorSequence(): Sequence> = sequence { check(shape.size >= 1) {"todo"} - val vectorOffset = linearStructure.strides[0] + val n = shape.size + val vectorOffset = shape[n - 1] val vectorShape = intArrayOf(shape.last()) for (offset in 0 until numel step vectorOffset) { val vector = BufferedTensor(vectorShape, buffer, offset).as1D() @@ -44,8 +45,9 @@ public open class BufferedTensor( public fun matrixSequence(): Sequence> = sequence { check(shape.size >= 2) {"todo"} - val matrixOffset = linearStructure.strides[1] - val matrixShape = intArrayOf(shape[shape.size - 2], shape.last()) //todo better way? + val n = shape.size + val matrixOffset = shape[n - 1] * shape[n - 2] + val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) //todo better way? for (offset in 0 until numel step matrixOffset) { val matrix = BufferedTensor(matrixShape, buffer, offset).as2D() yield(matrix) From e01ca38fb3a7b05037582f561298928be552100e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 23 Mar 2021 13:51:52 +0000 Subject: [PATCH 129/393] Tasks for Andrei and Alya --- .../kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 8 ++++---- .../kscience/kmath/tensors/core/DoubleTensorAlgebra.kt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index e0abc49b7..8a16a991d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -8,7 +8,7 @@ public class DoubleLinearOpsTensorAlgebra : DoubleTensorAlgebra() { override fun DoubleTensor.inv(): DoubleTensor { - TODO("Not yet implemented") + TODO("ANDREI") } override fun DoubleTensor.lu(tol: Double): Pair { @@ -135,16 +135,16 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.qr(): DoubleTensor { - TODO("Not yet implemented") + TODO("ANDREI") } override fun DoubleTensor.svd(): Triple { - TODO("Not yet implemented") + TODO("ALYA") } override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { - TODO("Not yet implemented") + TODO("ANDREI") } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 67b50970b..c67687a09 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -262,7 +262,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Date: Wed, 24 Mar 2021 14:00:47 +0300 Subject: [PATCH 130/393] fix --- .../space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt | 2 +- .../kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index c4fa3e0a8..e412af7c6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -14,7 +14,7 @@ public interface LinearOpsTensorAlgebra, Inde public fun TensorType.qr(): TensorType //https://pytorch.org/docs/stable/generated/torch.lu.html - public fun TensorType.lu(tol: T): Pair + public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html public fun luPivot(luTensor: TensorType, pivotsTensor: IndexTensorType): Triple diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index e0abc49b7..d090ce79c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -11,7 +11,7 @@ public class DoubleLinearOpsTensorAlgebra : TODO("Not yet implemented") } - override fun DoubleTensor.lu(tol: Double): Pair { + override fun DoubleTensor.lu(): Pair { checkSquareMatrix(shape) @@ -138,7 +138,6 @@ public class DoubleLinearOpsTensorAlgebra : TODO("Not yet implemented") } - override fun DoubleTensor.svd(): Triple { TODO("Not yet implemented") } From cd05ca6e952ad4475301c4e0b47c0f6c100e57d9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 24 Mar 2021 16:36:06 +0300 Subject: [PATCH 131/393] Initial Optimization API --- build.gradle.kts | 5 +- .../commons/optimization/CMOptimization.kt | 20 ++-- .../kmath/commons/optimization/cmFit.kt | 17 ++-- kmath-core/api/kmath-core.api | 35 +++---- .../space/kscience/kmath/data/ColumnarData.kt | 34 +++++++ .../kscience/kmath/data/XYColumnarData.kt | 55 +++++++++++ .../kscience/kmath/data/XYZColumnarData.kt | 21 ++++ .../space/kscience/kmath/misc/ColumnarData.kt | 15 --- .../space/kscience/kmath/misc/XYPointSet.kt | 98 ------------------- .../kmath/interpolation/Interpolator.kt | 16 +-- .../kmath/interpolation/LinearInterpolator.kt | 6 +- .../kmath/interpolation/SplineInterpolator.kt | 4 +- .../kotlingrad/DifferentiableMstExpression.kt | 6 +- .../kscience/kmath/optimization/DataFit.kt | 17 ---- .../optimization/FunctionOptimization.kt | 80 ++++----------- .../NoDerivFunctionOptimization.kt | 69 +++++++++++++ .../kscience/kmath/optimization/XYFit.kt | 40 ++++++++ settings.gradle.kts | 5 +- 18 files changed, 296 insertions(+), 247 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/ColumnarData.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/XYPointSet.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/DataFit.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt diff --git a/build.gradle.kts b/build.gradle.kts index d4453ad5c..cc863a957 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,10 +11,7 @@ allprojects { jcenter() maven("https://clojars.org/repo") maven("https://dl.bintray.com/egor-bogomolov/astminer/") - maven("https://dl.bintray.com/kotlin/kotlin-eap") - maven("https://dl.bintray.com/kotlin/kotlinx") - maven("https://dl.bintray.com/mipt-npm/dev") - maven("https://dl.bintray.com/mipt-npm/kscience") + maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://jitpack.io") maven("http://logicrunch.research.it.uu.se/maven/") mavenCentral() diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt index 93d0f0bba..444c505c9 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt @@ -15,10 +15,7 @@ import space.kscience.kmath.expressions.SymbolIndexer import space.kscience.kmath.expressions.derivative import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.optimization.FunctionOptimization -import space.kscience.kmath.optimization.OptimizationFeature -import space.kscience.kmath.optimization.OptimizationProblemFactory -import space.kscience.kmath.optimization.OptimizationResult +import space.kscience.kmath.optimization.* import kotlin.reflect.KClass public operator fun PointValuePair.component1(): DoubleArray = point @@ -27,7 +24,8 @@ public operator fun PointValuePair.component2(): Double = value @OptIn(UnstableKMathAPI::class) public class CMOptimization( override val symbols: List, -) : FunctionOptimization, SymbolIndexer, OptimizationFeature { +) : FunctionOptimization, NoDerivFunctionOptimization, SymbolIndexer, OptimizationFeature { + private val optimizationData: HashMap, OptimizationData> = HashMap() private var optimizerBuilder: (() -> MultivariateOptimizer)? = null public var convergenceChecker: ConvergenceChecker = SimpleValueChecker( @@ -36,6 +34,12 @@ public class CMOptimization( DEFAULT_MAX_ITER ) + override var maximize: Boolean + get() = optimizationData[GoalType::class] == GoalType.MAXIMIZE + set(value) { + optimizationData[GoalType::class] = if (value) GoalType.MAXIMIZE else GoalType.MINIMIZE + } + public fun addOptimizationData(data: OptimizationData) { optimizationData[data::class] = data } @@ -50,7 +54,7 @@ public class CMOptimization( addOptimizationData(InitialGuess(map.toDoubleArray())) } - public override fun expression(expression: Expression): Unit { + public override fun function(expression: Expression): Unit { val objectiveFunction = ObjectiveFunction { val args = it.toMap() expression(args) @@ -58,8 +62,8 @@ public class CMOptimization( addOptimizationData(objectiveFunction) } - public override fun diffExpression(expression: DifferentiableExpression>) { - expression(expression) + public override fun diffFunction(expression: DifferentiableExpression>) { + function(expression) val gradientFunction = ObjectiveFunctionGradient { val args = it.toMap() DoubleArray(symbols.size) { index -> diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt index 8e9ce7a80..f84dae693 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt @@ -1,13 +1,13 @@ package space.kscience.kmath.commons.optimization import org.apache.commons.math3.analysis.differentiation.DerivativeStructure -import org.apache.commons.math3.optim.nonlinear.scalar.GoalType import space.kscience.kmath.commons.expressions.DerivativeStructureField import space.kscience.kmath.expressions.DifferentiableExpression import space.kscience.kmath.expressions.Expression import space.kscience.kmath.misc.Symbol import space.kscience.kmath.optimization.FunctionOptimization import space.kscience.kmath.optimization.OptimizationResult +import space.kscience.kmath.optimization.noDerivOptimizeWith import space.kscience.kmath.optimization.optimizeWith import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer @@ -44,7 +44,7 @@ public fun FunctionOptimization.Companion.chiSquared( public fun Expression.optimize( vararg symbols: Symbol, configuration: CMOptimization.() -> Unit, -): OptimizationResult = optimizeWith(CMOptimization, symbols = symbols, configuration) +): OptimizationResult = noDerivOptimizeWith(CMOptimization, symbols = symbols, configuration) /** * Optimize differentiable expression @@ -58,10 +58,11 @@ public fun DifferentiableExpression>.minimize( vararg startPoint: Pair, configuration: CMOptimization.() -> Unit = {}, ): OptimizationResult { - require(startPoint.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = CMOptimization(startPoint.map { it.first }).apply(configuration) - problem.diffExpression(this) - problem.initialGuess(startPoint.toMap()) - problem.goal(GoalType.MINIMIZE) - return problem.optimize() + val symbols = startPoint.map { it.first }.toTypedArray() + return optimize(*symbols){ + maximize = false + initialGuess(startPoint.toMap()) + diffFunction(this@minimize) + configuration() + } } \ No newline at end of file diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 570e50a86..e6f4697aa 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -1,3 +1,18 @@ +public final class space/kscience/kmath/data/ColumnarDataKt { +} + +public final class space/kscience/kmath/data/XYColumnarData$DefaultImpls { + public static fun get (Lspace/kscience/kmath/data/XYColumnarData;Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer; +} + +public final class space/kscience/kmath/data/XYColumnarDataKt { + public static synthetic fun asXYData$default (Lspace/kscience/kmath/nd/Structure2D;IIILjava/lang/Object;)Lspace/kscience/kmath/data/XYColumnarData; +} + +public final class space/kscience/kmath/data/XYZColumnarData$DefaultImpls { + public static fun get (Lspace/kscience/kmath/data/XYZColumnarData;Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer; +} + public abstract interface class space/kscience/kmath/domains/Domain { public abstract fun contains (Lspace/kscience/kmath/structures/Buffer;)Z public abstract fun getDimension ()I @@ -603,15 +618,6 @@ public final class space/kscience/kmath/misc/CumulativeKt { public static final fun cumulativeSumOfLong (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; } -public final class space/kscience/kmath/misc/NDStructureColumn : space/kscience/kmath/structures/Buffer { - public fun (Lspace/kscience/kmath/nd/Structure2D;I)V - public fun get (I)Ljava/lang/Object; - public final fun getColumn ()I - public fun getSize ()I - public final fun getStructure ()Lspace/kscience/kmath/nd/Structure2D; - public fun iterator ()Ljava/util/Iterator; -} - public final class space/kscience/kmath/misc/StringSymbol : space/kscience/kmath/misc/Symbol { public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/misc/StringSymbol; public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; @@ -644,17 +650,6 @@ public final class space/kscience/kmath/misc/SymbolKt { public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation { } -public final class space/kscience/kmath/misc/XYPointSet$DefaultImpls { - public static fun get (Lspace/kscience/kmath/misc/XYPointSet;Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer; -} - -public final class space/kscience/kmath/misc/XYPointSetKt { -} - -public final class space/kscience/kmath/misc/XYZPointSet$DefaultImpls { - public static fun get (Lspace/kscience/kmath/misc/XYZPointSet;Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer; -} - public abstract interface class space/kscience/kmath/nd/AlgebraND { public static final field Companion Lspace/kscience/kmath/nd/AlgebraND$Companion; public abstract fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt new file mode 100644 index 000000000..761255158 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt @@ -0,0 +1,34 @@ +package space.kscience.kmath.data + +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.Structure2D +import space.kscience.kmath.structures.Buffer + +/** + * A column-based data set with all columns of the same size (not necessary fixed in time). + * The column could be retrieved by a [get] operation. + */ +@UnstableKMathAPI +public interface ColumnarData { + public val size: Int + + public operator fun get(symbol: Symbol): Buffer +} + +/** + * A zero-copy method to represent a [Structure2D] as a two-column x-y data. + * There could more than two columns in the structure. + */ +@UnstableKMathAPI +public fun Structure2D.asColumnarData(mapping: Map): ColumnarData { + require(shape[1] >= mapping.maxOf { it.value }) { "Column index out of bounds" } + return object : ColumnarData { + override val size: Int get() = shape[0] + override fun get(symbol: Symbol): Buffer { + val index = mapping[symbol] ?: error("No column mapping for symbol $symbol") + return columns[index] + } + } +} + diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt new file mode 100644 index 000000000..15239bca1 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt @@ -0,0 +1,55 @@ +package space.kscience.kmath.data + +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.Structure2D +import space.kscience.kmath.structures.Buffer +import kotlin.math.max + +/** + * The buffer of X values. + */ +@UnstableKMathAPI +public interface XYColumnarData : ColumnarData { + /** + * The buffer of X values + */ + public val x: Buffer + + /** + * The buffer of Y values. + */ + public val y: Buffer + + override fun get(symbol: Symbol): Buffer = when (symbol) { + Symbol.x -> x + Symbol.y -> y + else -> error("A column for symbol $symbol not found") + } +} + +@Suppress("FunctionName") +@UnstableKMathAPI +public fun XYColumnarData(x: Buffer, y: Buffer): XYColumnarData { + require(x.size == y.size) { "Buffer size mismatch. x buffer size is ${x.size}, y buffer size is ${y.size}" } + return object : XYColumnarData { + override val size: Int = x.size + override val x: Buffer = x + override val y: Buffer = y + } +} + + +/** + * A zero-copy method to represent a [Structure2D] as a two-column x-y data. + * There could more than two columns in the structure. + */ +@UnstableKMathAPI +public fun Structure2D.asXYData(xIndex: Int = 0, yIndex: Int = 1): XYColumnarData { + require(shape[1] >= max(xIndex, yIndex)) { "Column index out of bounds" } + return object : XYColumnarData { + override val size: Int get() = this@asXYData.shape[0] + override val x: Buffer get() = columns[xIndex] + override val y: Buffer get() = columns[yIndex] + } +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt new file mode 100644 index 000000000..f74c6e2d6 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt @@ -0,0 +1,21 @@ +package space.kscience.kmath.data + +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.structures.Buffer + +/** + * A [XYColumnarData] with guaranteed [x], [y] and [z] columns designated by corresponding symbols. + * Inherits [XYColumnarData]. + */ +@UnstableKMathAPI +public interface XYZColumnarData : XYColumnarData { + public val z: Buffer + + override fun get(symbol: Symbol): Buffer = when (symbol) { + Symbol.x -> x + Symbol.y -> y + Symbol.z -> z + else -> error("A column for symbol $symbol not found") + } +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/ColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/ColumnarData.kt deleted file mode 100644 index ed5a7e8f0..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/ColumnarData.kt +++ /dev/null @@ -1,15 +0,0 @@ -package space.kscience.kmath.misc - -import space.kscience.kmath.structures.Buffer - -/** - * A column-based data set with all columns of the same size (not necessary fixed in time). - * The column could be retrieved by a [get] operation. - */ -@UnstableKMathAPI -public interface ColumnarData { - public val size: Int - - public operator fun get(symbol: Symbol): Buffer -} - diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/XYPointSet.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/XYPointSet.kt deleted file mode 100644 index 51582974f..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/XYPointSet.kt +++ /dev/null @@ -1,98 +0,0 @@ -package space.kscience.kmath.misc - -import space.kscience.kmath.nd.Structure2D -import space.kscience.kmath.structures.Buffer - -/** - * Pair of associated buffers for X and Y axes values. - * - * @param X the type of X values. - * @param Y the type of Y values. - */ -public interface XYPointSet { - /** - * The size of all the involved buffers. - */ - public val size: Int - - /** - * The buffer of X values. - */ -@UnstableKMathAPI -public interface XYPointSet : ColumnarData { - public val x: Buffer - - /** - * The buffer of Y values. - */ - public val y: Buffer - - override fun get(symbol: Symbol): Buffer = when (symbol) { - Symbol.x -> x - Symbol.y -> y - else -> error("A column for symbol $symbol not found") - } -} - -/** - * Triple of associated buffers for X, Y, and Z axes values. - * - * @param X the type of X values. - * @param Y the type of Y values. - * @param Z the type of Z values. - */ -public interface XYZPointSet : XYPointSet { - /** - * The buffer of Z values. - */ -@UnstableKMathAPI -public interface XYZPointSet : XYPointSet { - public val z: Buffer - - override fun get(symbol: Symbol): Buffer = when (symbol) { - Symbol.x -> x - Symbol.y -> y - Symbol.z -> z - else -> error("A column for symbol $symbol not found") - } -} - -internal fun > insureSorted(points: XYPointSet) { - for (i in 0 until points.size - 1) - require(points.x[i + 1] > points.x[i]) { "Input data is not sorted at index $i" } -} - -public class NDStructureColumn(public val structure: Structure2D, public val column: Int) : Buffer { - public override val size: Int - get() = structure.rowNum - - init { - require(column < structure.colNum) { "Column index is outside of structure column range" } - } - - public override operator fun get(index: Int): T = structure[index, column] - public override operator fun iterator(): Iterator = sequence { repeat(size) { yield(get(it)) } }.iterator() -} - -@UnstableKMathAPI -public class BufferXYPointSet( - public override val x: Buffer, - public override val y: Buffer, -) : XYPointSet { - public override val size: Int get() = x.size - - init { - require(x.size == y.size) { "Sizes of x and y buffers should be the same" } - } -} - -@UnstableKMathAPI -public fun Structure2D.asXYPointSet(): XYPointSet { - require(shape[1] == 2) { "Structure second dimension should be of size 2" } - - return object : XYPointSet { - override val size: Int get() = this@asXYPointSet.shape[0] - override val x: Buffer get() = NDStructureColumn(this@asXYPointSet, 0) - override val y: Buffer get() = NDStructureColumn(this@asXYPointSet, 1) - } -} diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt index 864431d7a..9fad30abb 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -1,17 +1,17 @@ @file:OptIn(UnstableKMathAPI::class) + package space.kscience.kmath.interpolation +import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.value -import space.kscience.kmath.misc.BufferXYPointSet import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.misc.XYPointSet import space.kscience.kmath.operations.Ring import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer public fun interface Interpolator { - public fun interpolate(points: XYPointSet): (X) -> Y + public fun interpolate(points: XYColumnarData): (X) -> Y } public interface PolynomialInterpolator> : Interpolator { @@ -19,9 +19,9 @@ public interface PolynomialInterpolator> : Interpolator): PiecewisePolynomial + public fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial - override fun interpolate(points: XYPointSet): (T) -> T = { x -> + override fun interpolate(points: XYColumnarData): (T) -> T = { x -> interpolatePolynomials(points).value(algebra, x) ?: getDefaultValue() } } @@ -31,20 +31,20 @@ public fun > PolynomialInterpolator.interpolatePolynomials( x: Buffer, y: Buffer, ): PiecewisePolynomial { - val pointSet = BufferXYPointSet(x, y) + val pointSet = XYColumnarData(x, y) return interpolatePolynomials(pointSet) } public fun > PolynomialInterpolator.interpolatePolynomials( data: Map, ): PiecewisePolynomial { - val pointSet = BufferXYPointSet(data.keys.toList().asBuffer(), data.values.toList().asBuffer()) + val pointSet = XYColumnarData(data.keys.toList().asBuffer(), data.values.toList().asBuffer()) return interpolatePolynomials(pointSet) } public fun > PolynomialInterpolator.interpolatePolynomials( data: List>, ): PiecewisePolynomial { - val pointSet = BufferXYPointSet(data.map { it.first }.asBuffer(), data.map { it.second }.asBuffer()) + val pointSet = XYColumnarData(data.map { it.first }.asBuffer(), data.map { it.second }.asBuffer()) return interpolatePolynomials(pointSet) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt index 89a242ece..37d378ad0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt @@ -1,15 +1,15 @@ package space.kscience.kmath.interpolation +import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.functions.OrderedPiecewisePolynomial import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.misc.XYPointSet import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.invoke @OptIn(UnstableKMathAPI::class) -internal fun > insureSorted(points: XYPointSet<*, T, *>) { +internal fun > insureSorted(points: XYColumnarData<*, T, *>) { for (i in 0 until points.size - 1) require(points.x[i + 1] > points.x[i]) { "Input data is not sorted at index $i" } } @@ -19,7 +19,7 @@ internal fun > insureSorted(points: XYPointSet<*, T, *>) { */ public class LinearInterpolator>(public override val algebra: Field) : PolynomialInterpolator { @OptIn(UnstableKMathAPI::class) - public override fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial = algebra { + public override fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial = algebra { require(points.size > 0) { "Point array should not be empty" } insureSorted(points) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index 0756e2901..3a3dfab59 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -1,10 +1,10 @@ package space.kscience.kmath.interpolation +import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.functions.OrderedPiecewisePolynomial import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.misc.XYPointSet import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.MutableBufferFactory @@ -23,7 +23,7 @@ public class SplineInterpolator>( //TODO possibly optimize zeroed buffers @OptIn(UnstableKMathAPI::class) - public override fun interpolatePolynomials(points: XYPointSet): PiecewisePolynomial = algebra { + public override fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial = algebra { require(points.size >= 3) { "Can't use spline interpolator with less than 3 points" } insureSorted(points) // Number of intervals. The number of data points is n + 1. diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt index fe27b7e4d..1275b0c90 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -18,8 +18,10 @@ import space.kscience.kmath.operations.NumericAlgebra * @param A the [NumericAlgebra] of [T]. * @property expr the underlying [MstExpression]. */ -public inline class DifferentiableMstExpression(public val expr: MstExpression) : - DifferentiableExpression> where A : NumericAlgebra, T : Number { +public inline class DifferentiableMstExpression( + public val expr: MstExpression, +) : DifferentiableExpression> where A : NumericAlgebra { + public constructor(algebra: A, mst: MST) : this(MstExpression(algebra, mst)) /** diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/DataFit.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/DataFit.kt deleted file mode 100644 index 70dd8417c..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/DataFit.kt +++ /dev/null @@ -1,17 +0,0 @@ -package space.kscience.kmath.optimization - -import space.kscience.kmath.expressions.DifferentiableExpression -import space.kscience.kmath.misc.StringSymbol -import space.kscience.kmath.misc.Symbol -import space.kscience.kmath.structures.Buffer - -public interface DataFit : Optimization { - - public fun modelAndData( - x: Buffer, - y: Buffer, - yErr: Buffer, - model: DifferentiableExpression, - xSymbol: Symbol = StringSymbol("x"), - ) -} \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt index 02aa9e9bb..528a5744e 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt @@ -4,45 +4,31 @@ import space.kscience.kmath.expressions.AutoDiffProcessor import space.kscience.kmath.expressions.DifferentiableExpression import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.ExpressionAlgebra -import space.kscience.kmath.misc.StringSymbol import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.indices -import kotlin.math.pow /** - * A likelihood function optimization problem + * A likelihood function optimization problem with provided derivatives */ -public interface FunctionOptimization: Optimization, DataFit { +public interface FunctionOptimization : Optimization { + /** + * The optimization direction. If true search for function maximum, if false, search for the minimum + */ + public var maximize: Boolean + /** * Define the initial guess for the optimization problem */ public fun initialGuess(map: Map) - /** - * Set an objective function expression - */ - public fun expression(expression: Expression) - /** * Set a differentiable expression as objective function as function and gradient provider */ - public fun diffExpression(expression: DifferentiableExpression>) + public fun diffFunction(expression: DifferentiableExpression>) - override fun modelAndData( - x: Buffer, - y: Buffer, - yErr: Buffer, - model: DifferentiableExpression, - xSymbol: Symbol, - ) { - require(x.size == y.size) { "X and y buffers should be of the same size" } - require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } - - } - - public companion object{ + public companion object { /** * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation */ @@ -70,46 +56,22 @@ public interface FunctionOptimization: Optimization, DataFit { sum } } - - /** - * Generate a chi squared expression from given x-y-sigma model represented by an expression. Does not provide derivatives - */ - public fun chiSquared( - x: Buffer, - y: Buffer, - yErr: Buffer, - model: Expression, - xSymbol: Symbol = StringSymbol("x"), - ): Expression { - require(x.size == y.size) { "X and y buffers should be of the same size" } - require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } - - return Expression { arguments -> - x.indices.sumByDouble { - val xValue = x[it] - val yValue = y[it] - val yErrValue = yErr[it] - val modifiedArgs = arguments + (xSymbol to xValue) - val modelValue = model(modifiedArgs) - ((yValue - modelValue) / yErrValue).pow(2) - } - } - } } } /** - * Optimize expression without derivatives using specific [OptimizationProblemFactory] + * Define a chi-squared-based objective function */ -public fun > Expression.optimizeWith( - factory: OptimizationProblemFactory, - vararg symbols: Symbol, - configuration: F.() -> Unit, -): OptimizationResult { - require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } - val problem = factory(symbols.toList(), configuration) - problem.expression(this) - return problem.optimize() +public fun FunctionOptimization.chiSquared( + autoDiff: AutoDiffProcessor>, + x: Buffer, + y: Buffer, + yErr: Buffer, + model: A.(I) -> I, +) where A : ExtendedField, A : ExpressionAlgebra { + val chiSquared = FunctionOptimization.chiSquared(autoDiff, x, y, yErr, model) + diffFunction(chiSquared) + maximize = false } /** @@ -122,6 +84,6 @@ public fun > DifferentiableExpression { require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } val problem = factory(symbols.toList(), configuration) - problem.diffExpression(this) + problem.diffFunction(this) return problem.optimize() } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt new file mode 100644 index 000000000..b8785dd8c --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt @@ -0,0 +1,69 @@ +package space.kscience.kmath.optimization + +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.indices +import kotlin.math.pow + +/** + * A likelihood function optimization problem + */ +public interface NoDerivFunctionOptimization : Optimization { + /** + * The optimization direction. If true search for function maximum, if false, search for the minimum + */ + public var maximize: Boolean + + /** + * Define the initial guess for the optimization problem + */ + public fun initialGuess(map: Map) + + /** + * Set an objective function expression + */ + public fun function(expression: Expression) + + public companion object { + /** + * Generate a chi squared expression from given x-y-sigma model represented by an expression. Does not provide derivatives + */ + public fun chiSquared( + x: Buffer, + y: Buffer, + yErr: Buffer, + model: Expression, + xSymbol: Symbol = Symbol.x, + ): Expression { + require(x.size == y.size) { "X and y buffers should be of the same size" } + require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } + + return Expression { arguments -> + x.indices.sumByDouble { + val xValue = x[it] + val yValue = y[it] + val yErrValue = yErr[it] + val modifiedArgs = arguments + (xSymbol to xValue) + val modelValue = model(modifiedArgs) + ((yValue - modelValue) / yErrValue).pow(2) + } + } + } + } +} + + +/** + * Optimize expression without derivatives using specific [OptimizationProblemFactory] + */ +public fun > Expression.noDerivOptimizeWith( + factory: OptimizationProblemFactory, + vararg symbols: Symbol, + configuration: F.() -> Unit, +): OptimizationResult { + require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" } + val problem = factory(symbols.toList(), configuration) + problem.function(this) + return problem.optimize() +} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt new file mode 100644 index 000000000..c3106c819 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt @@ -0,0 +1,40 @@ +package space.kscience.kmath.optimization + +import space.kscience.kmath.data.ColumnarData +import space.kscience.kmath.expressions.AutoDiffProcessor +import space.kscience.kmath.expressions.DifferentiableExpression +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.ExpressionAlgebra +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.operations.Field + +@UnstableKMathAPI +public interface XYFit : Optimization { + + public val algebra: Field + + /** + * Set X-Y data for this fit optionally including x and y errors + */ + public fun data( + dataSet: ColumnarData, + xSymbol: Symbol, + ySymbol: Symbol, + xErrSymbol: Symbol? = null, + yErrSymbol: Symbol? = null, + ) + + public fun model(model: (T) -> DifferentiableExpression) + + /** + * Set the differentiable model for this fit + */ + public fun model( + autoDiff: AutoDiffProcessor>, + modelFunction: A.(I) -> I, + ): Unit where A : ExtendedField, A : ExpressionAlgebra = model { arg -> + autoDiff.process { modelFunction(const(arg)) } + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index b4d7b3049..4467d5ed6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,12 +4,11 @@ pluginManagement { mavenLocal() gradlePluginPortal() jcenter() - maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/kotlin/kotlinx") } - val toolsVersion = "0.9.1" - val kotlinVersion = "1.4.31" + val toolsVersion = "0.9.3" + val kotlinVersion = "1.4.32" plugins { id("kotlinx.benchmark") version "0.2.0-dev-20" From 206bcfc909d56a859ec783a30cc75a8ade178786 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 24 Mar 2021 18:08:36 +0300 Subject: [PATCH 132/393] lu inv and det complete + tests --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 2 +- .../core/DoubleLinearOpsTensorAlgebra.kt | 79 +++++++++++++++++++ .../kmath/tensors/core/DoubleTensorAlgebra.kt | 35 +++++++- .../core/TestDoubleAnalyticTensorAlgebra.kt | 7 +- .../core/TestDoubleLinearOpsAlgebra.kt | 73 +++++++++++++++++ 5 files changed, 187 insertions(+), 9 deletions(-) create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index e412af7c6..f551d524a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -13,7 +13,7 @@ public interface LinearOpsTensorAlgebra, Inde //https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr public fun TensorType.qr(): TensorType - //https://pytorch.org/docs/stable/generated/torch.lu.html + //htt ps://pytorch.org/docs/stable/generated/torch.lu.html public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 7779ad029..c8c4c413f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,5 +1,8 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.nd.Structure1D +import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import kotlin.math.sqrt @@ -20,6 +23,8 @@ public class DoubleLinearOpsTensorAlgebra : val n = shape.size val m = shape.last() val pivotsShape = IntArray(n - 1) { i -> shape[i] } + pivotsShape[n - 2] = m + 1 + val pivotsTensor = IntTensor( pivotsShape, IntArray(pivotsShape.reduce(Int::times)) { 0 } @@ -54,6 +59,8 @@ public class DoubleLinearOpsTensorAlgebra : lu[maxInd, k] = tmp } + pivots[m] += 1 + } for (j in i + 1 until m) { @@ -146,6 +153,78 @@ public class DoubleLinearOpsTensorAlgebra : TODO("ANDREI") } + private fun luMatrixDet(lu: Structure2D, pivots: Structure1D): Double { + val m = lu.shape[0] + val sign = if((pivots[m] - m) % 2 == 0) 1.0 else -1.0 + var det = sign + for (i in 0 until m){ + det *= lu[i, i] + } + return det + } + + public fun DoubleTensor.detLU(): DoubleTensor { + val (luTensor, pivotsTensor) = this.lu() + val n = shape.size + + val detTensorShape = IntArray(n - 1) { i -> shape[i] } + detTensorShape[n - 2] = 1 + val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } + + val detTensor = DoubleTensor( + detTensorShape, + resBuffer + ) + + luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (luMatrix, pivots) -> + resBuffer[index] = luMatrixDet(luMatrix, pivots) + } + + return detTensor + } + + private fun luMatrixInv( + lu: Structure2D, + pivots: Structure1D, + invMatrix : MutableStructure2D + ): Unit { + val m = lu.shape[0] + + for (j in 0 until m) { + for (i in 0 until m) { + if (pivots[i] == j){ + invMatrix[i, j] = 1.0 + } + + for (k in 0 until i){ + invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] + } + } + + for (i in m - 1 downTo 0) { + for (k in i + 1 until m) { + invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] + } + invMatrix[i, j] /= lu[i, i] + } + } + } + + public fun DoubleTensor.invLU(): DoubleTensor { + val (luTensor, pivotsTensor) = this.lu() + val n = shape.size + val invTensor = luTensor.zeroesLike() + + for ( + (luP, invMatrix) in + luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) + ) { + val (lu, pivots) = luP + luMatrixInv(lu, pivots, invMatrix) + } + + return invTensor + } } public inline fun DoubleLinearOpsTensorAlgebra(block: DoubleLinearOpsTensorAlgebra.() -> R): R = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index c67687a09..ff65ca027 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,5 +1,8 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra import kotlin.math.abs @@ -262,7 +265,31 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra shape[i] } + detTensorShape[n - 1] = 1 + val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } + + val detTensor = DoubleTensor( + detTensorShape, + resBuffer + ) + + this.matrixSequence().forEachIndexed{i, matrix -> + // todo need Matrix determinant algo + // todo resBuffer[i] = matrix.det() + } + + + return detTensor + + */ } override fun DoubleTensor.square(): DoubleTensor { @@ -294,7 +321,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Boolean): Boolean { - if (!(this.shape contentEquals other.shape)){ + if (!(this.shape contentEquals other.shape)) { return false } return this.eq(other, eqFunction) @@ -303,10 +330,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Boolean): Boolean { // todo broadcasting checking val n = this.linearStructure.size - if (n != other.linearStructure.size){ + if (n != other.linearStructure.size) { return false } - for (i in 0 until n){ + for (i in 0 until n) { if (!eqFunction(this.buffer[this.bufferStart + i], other.buffer[other.bufferStart + i])) { return false } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 8028ce175..4dcdb7848 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -3,7 +3,6 @@ package space.kscience.kmath.tensors.core import kotlin.math.abs import kotlin.math.exp import kotlin.test.Test -import kotlin.test.assertEquals import kotlin.test.assertTrue class TestDoubleAnalyticTensorAlgebra { @@ -16,9 +15,9 @@ class TestDoubleAnalyticTensorAlgebra { return this.map(transform).toDoubleArray() } - fun DoubleArray.deltaEqual(other: DoubleArray, delta: Double = 1e-5): Boolean { + fun DoubleArray.epsEqual(other: DoubleArray, eps: Double = 1e-5): Boolean { for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) { - if (abs(elem1 - elem2) > delta) { + if (abs(elem1 - elem2) > eps) { return false } } @@ -29,7 +28,7 @@ class TestDoubleAnalyticTensorAlgebra { fun testExp() = DoubleAnalyticTensorAlgebra { tensor.exp().let { assertTrue { shape contentEquals it.shape } - assertTrue { buffer.fmap(::exp).deltaEqual(it.buffer.array())} + assertTrue { buffer.fmap(::exp).epsEqual(it.buffer.array())} } } } \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt new file mode 100644 index 000000000..2da79382f --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -0,0 +1,73 @@ +package space.kscience.kmath.tensors.core + +import kotlin.math.abs +import kotlin.math.exp +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class TestDoubleLinearOpsTensorAlgebra { + + private val eps = 1e-5 + + private fun Double.epsEqual(other: Double): Boolean { + return abs(this - other) < eps + } + + fun DoubleArray.epsEqual(other: DoubleArray, eps: Double = 1e-5): Boolean { + for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) { + if (abs(elem1 - elem2) > eps) { + return false + } + } + return true + } + + @Test + fun testDetLU() = DoubleLinearOpsTensorAlgebra { + val tensor = fromArray( + intArrayOf(2, 2, 2), + doubleArrayOf( + 1.0, 3.0, + 1.0, 2.0, + 1.5, 1.0, + 10.0, 2.0 + ) + ) + + val expectedShape = intArrayOf(2, 1) + val expectedBuffer = doubleArrayOf( + -1.0, + -7.0 + ) + val detTensor = tensor.detLU() + + assertTrue { detTensor.shape contentEquals expectedShape } + assertTrue { detTensor.buffer.array().epsEqual(expectedBuffer) } + } + + @Test + fun testInvLU() = DoubleLinearOpsTensorAlgebra { + val tensor = fromArray( + intArrayOf(2, 2, 2), + doubleArrayOf( + 1.0, 0.0, + 0.0, 2.0, + 1.0, 1.0, + 1.0, 0.0 + ) + ) + + val expectedShape = intArrayOf(2, 2, 2) + val expectedBuffer = doubleArrayOf( + 1.0, 0.0, + 0.0, 0.5, + 0.0, 1.0, + 1.0, -1.0 + ) + + val invTensor = tensor.invLU() + assertTrue { invTensor.shape contentEquals expectedShape } + assertTrue { invTensor.buffer.array().epsEqual(expectedBuffer) } + } +} From ab8137000146c52f10b3213c960b03917a0ada4f Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 24 Mar 2021 18:42:41 +0300 Subject: [PATCH 133/393] fixes --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 2 +- .../core/DoubleLinearOpsTensorAlgebra.kt | 22 +++++++------------ 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index f551d524a..e412af7c6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -13,7 +13,7 @@ public interface LinearOpsTensorAlgebra, Inde //https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr public fun TensorType.qr(): TensorType - //htt ps://pytorch.org/docs/stable/generated/torch.lu.html + //https://pytorch.org/docs/stable/generated/torch.lu.html public fun TensorType.lu(): Pair //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index c8c4c413f..0b9d824f0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -10,9 +10,9 @@ public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, DoubleTensorAlgebra() { - override fun DoubleTensor.inv(): DoubleTensor { - TODO("ANDREI") - } + override fun DoubleTensor.inv(): DoubleTensor = invLU() + + override fun DoubleTensor.det(): DoubleTensor = detLU() override fun DoubleTensor.lu(): Pair { @@ -156,15 +156,11 @@ public class DoubleLinearOpsTensorAlgebra : private fun luMatrixDet(lu: Structure2D, pivots: Structure1D): Double { val m = lu.shape[0] val sign = if((pivots[m] - m) % 2 == 0) 1.0 else -1.0 - var det = sign - for (i in 0 until m){ - det *= lu[i, i] - } - return det + return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } } public fun DoubleTensor.detLU(): DoubleTensor { - val (luTensor, pivotsTensor) = this.lu() + val (luTensor, pivotsTensor) = lu() val n = shape.size val detTensorShape = IntArray(n - 1) { i -> shape[i] } @@ -211,14 +207,12 @@ public class DoubleLinearOpsTensorAlgebra : } public fun DoubleTensor.invLU(): DoubleTensor { - val (luTensor, pivotsTensor) = this.lu() + val (luTensor, pivotsTensor) = lu() val n = shape.size val invTensor = luTensor.zeroesLike() - for ( - (luP, invMatrix) in - luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) - ) { + val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) + for ((luP, invMatrix) in seq) { val (lu, pivots) = luP luMatrixInv(lu, pivots, invMatrix) } From a4aa4b80d27cecef092a1a411163e24ff70d08ec Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 24 Mar 2021 15:51:58 +0000 Subject: [PATCH 134/393] Updated API --- kmath-core/api/kmath-core.api | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 70bec600d..295df69e3 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2674,7 +2674,7 @@ public final class space/kscience/kmath/tensors/ComplexTensorStructure$DefaultIm public abstract interface class space/kscience/kmath/tensors/LinearOpsTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { public abstract fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun lu (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lkotlin/Pair; + public abstract fun lu (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; public abstract fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; public abstract fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; @@ -2884,10 +2884,14 @@ public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebr public fun ()V public synthetic fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun cholesky (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public fun det (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun detLU (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun inv (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun lu (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lkotlin/Pair; - public fun lu (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lkotlin/Pair; + public final fun invLU (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun lu (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; + public fun lu (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Pair; public synthetic fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; public fun luPivot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/IntTensor;)Lkotlin/Triple; public synthetic fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; From f70f60c0e8d5a3c830bc1ce577a63fa5ddfad290 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 24 Mar 2021 15:58:25 +0000 Subject: [PATCH 135/393] Moved det to LinearOps --- kmath-core/api/kmath-core.api | 4 +-- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 3 ++ .../kscience/kmath/tensors/TensorAlgebra.kt | 3 -- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 28 ------------------- 4 files changed, 4 insertions(+), 34 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 295df69e3..502628920 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2673,6 +2673,7 @@ public final class space/kscience/kmath/tensors/ComplexTensorStructure$DefaultIm public abstract interface class space/kscience/kmath/tensors/LinearOpsTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { public abstract fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun lu (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; public abstract fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; @@ -2706,7 +2707,6 @@ public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { public abstract fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun cumprod (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2958,8 +2958,6 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public fun cumprod (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public fun cumsum (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun det (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public fun diagonalEmbedding (Lspace/kscience/kmath/tensors/core/DoubleTensor;III)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index e412af7c6..3d1625a50 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -4,6 +4,9 @@ package space.kscience.kmath.tensors public interface LinearOpsTensorAlgebra, IndexTensorType: TensorStructure> : TensorPartialDivisionAlgebra { + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det + public fun TensorType.det(): TensorType + //https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv public fun TensorType.inv(): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index e41b7546c..702dc15e2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -52,9 +52,6 @@ public interface TensorAlgebra> { public fun TensorType.view(shape: IntArray): TensorType public fun TensorType.viewAs(other: TensorType): TensorType - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det - public fun TensorType.det(): TensorType - //https://pytorch.org/docs/stable/generated/torch.abs.html public fun TensorType.abs(): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 3ac09c8c7..df4a32bd8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -320,34 +320,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra shape[i] } - detTensorShape[n - 1] = 1 - val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } - - val detTensor = DoubleTensor( - detTensorShape, - resBuffer - ) - - this.matrixSequence().forEachIndexed{i, matrix -> - // todo need Matrix determinant algo - // todo resBuffer[i] = matrix.det() - } - - - return detTensor - - */ - } - override fun DoubleTensor.square(): DoubleTensor { TODO("Not yet implemented") } From 94b5afa6c475c4595ecb602f3ac1b66938ab04e6 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 24 Mar 2021 18:39:40 +0000 Subject: [PATCH 136/393] eq moved to interface --- .../kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt | 4 ++++ .../space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 702dc15e2..37c6a34f8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.tensors.core.DoubleTensor + // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { @@ -52,6 +54,8 @@ public interface TensorAlgebra> { public fun TensorType.view(shape: IntArray): TensorType public fun TensorType.viewAs(other: TensorType): TensorType + public fun TensorType.eq(other: TensorType, delta: T): Boolean + //https://pytorch.org/docs/stable/generated/torch.abs.html public fun TensorType.abs(): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index df4a32bd8..0c82ec9c8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -344,10 +344,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra abs(x - y) < delta } } - public fun DoubleTensor.eq(other: DoubleTensor, delta: Double = 1e-5): Boolean { + override fun DoubleTensor.eq(other: DoubleTensor, delta: Double): Boolean { return this.eq(other) { x, y -> abs(x - y) < delta } } + public fun DoubleTensor.eq(other: DoubleTensor): Boolean = this.eq(other, 1e-5) + public fun DoubleTensor.contentEquals(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { if (!(this.shape contentEquals other.shape)) { return false From daa077718299839d80256ef1705cb48f31d36c9f Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 24 Mar 2021 18:43:03 +0000 Subject: [PATCH 137/393] removed unused code --- .../kscience/kmath/tensors/core/checks.kt | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index ec7a123a9..c644a295c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -34,26 +34,6 @@ internal inline fun , } -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkDot(a: TensorType, b: TensorType): Unit { - val sa = a.shape - val sb = b.shape - val na = sa.size - val nb = sb.size - var status: Boolean - if (nb == 1) { - status = sa.last() == sb[0] - } else { - status = sa.last() == sb[nb - 2] - if ((na > 2) and (nb > 2)) { - status = status and - (sa.take(nb - 2).toIntArray() contentEquals sb.take(nb - 2).toIntArray()) - } - } - check(status) { "Incompatible shapes ${sa.toList()} and ${sb.toList()} provided for dot product" } -} - internal inline fun , TorchTensorAlgebraType : TensorAlgebra> TorchTensorAlgebraType.checkTranspose(dim: Int, i: Int, j: Int): Unit = From 1056fc7200b5fbbb03b75c66ca09c30483f12e5c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 13:48:59 +0000 Subject: [PATCH 138/393] Test for scalar product --- .../kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 2da79382f..d77f33f9d 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -70,4 +70,14 @@ class TestDoubleLinearOpsTensorAlgebra { assertTrue { invTensor.shape contentEquals expectedShape } assertTrue { invTensor.buffer.array().epsEqual(expectedBuffer) } } + + @Test + fun testScalarProduct() = DoubleLinearOpsTensorAlgebra { + val a = fromArray(intArrayOf(3), doubleArrayOf(1.8,2.5, 6.8)) + val b = fromArray(intArrayOf(3), doubleArrayOf(5.5,2.6, 6.4)) + DoubleReduceOpsTensorAlgebra { + assertEquals(a.dot(b).value(), 59.92) + } + + } } From 9162867fc28a4e948b0a520c67fca6cdf20ce53e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 14:37:27 +0000 Subject: [PATCH 139/393] Mutable structures 2D functionality added --- kmath-core/api/kmath-core.api | 17 ++++++++++++-- .../kscience/kmath/linear/LinearSpace.kt | 1 + .../space/kscience/kmath/nd/Structure2D.kt | 14 ++++++++++++ .../space/kscience/kmath/structures/Buffer.kt | 22 +++++++++++++++---- .../tensors/TensorPartialDivisionAlgebra.kt | 4 ++-- 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 502628920..a109aaab5 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -984,6 +984,8 @@ public final class space/kscience/kmath/nd/MutableStructure1D$DefaultImpls { } public abstract interface class space/kscience/kmath/nd/MutableStructure2D : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/Structure2D { + public abstract fun getColumns ()Ljava/util/List; + public abstract fun getRows ()Ljava/util/List; public abstract fun set (IILjava/lang/Object;)V } @@ -2608,6 +2610,15 @@ public final class space/kscience/kmath/structures/VirtualBuffer : space/kscienc public fun iterator ()Ljava/util/Iterator; } +public final class space/kscience/kmath/structures/VirtualMutableBuffer : space/kscience/kmath/structures/MutableBuffer { + public fun (ILkotlin/jvm/functions/Function1;)V + public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun get (I)Ljava/lang/Object; + public fun getSize ()I + public fun iterator ()Ljava/util/Iterator; + public fun set (ILjava/lang/Object;)V +} + public abstract interface class space/kscience/kmath/tensors/AnalyticTensorAlgebra : space/kscience/kmath/tensors/OrderedTensorAlgebra, space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { public abstract fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun acosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2709,6 +2720,7 @@ public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { public abstract fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun eq (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Z public abstract fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun flatten (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2970,9 +2982,10 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V public synthetic fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun dot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z + public synthetic fun eq (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Z + public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Z + public fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z - public static synthetic fun eq$default (Lspace/kscience/kmath/tensors/core/DoubleTensorAlgebra;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;DILjava/lang/Object;)Z public synthetic fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; public fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun flatten (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 6a587270b..4f2afc6fa 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -14,6 +14,7 @@ import kotlin.reflect.KClass * @param T the type of items. */ public typealias Matrix = Structure2D +public typealias MutableMatrix = MutableStructure2D /** * Alias or using [Buffer] as a point/vector in a many-dimensional space. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index d49438b2c..762b59b28 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -2,7 +2,9 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.VirtualBuffer +import space.kscience.kmath.structures.VirtualMutableBuffer import kotlin.reflect.KClass /** @@ -69,6 +71,18 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { * @param value the value. */ public operator fun set(i: Int, j: Int, value: T) + + /** + * The buffer of rows of this structure. It gets elements from the structure dynamically. + */ + override val rows: List> + get() = List(rowNum) { i -> VirtualMutableBuffer(colNum) { j -> get(i, j) } } + + /** + * The buffer of columns of this structure. It gets elements from the structure dynamically. + */ + override val columns: List> + get() = List(colNum) { j -> VirtualMutableBuffer(rowNum) { i -> get(i, j) } } } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index c85c6c5e3..72a6e3cae 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -223,11 +223,7 @@ public inline class MutableListBuffer(public val list: MutableList) : Muta } /** -<<<<<<< HEAD * Returns an [MutableListBuffer] that wraps the original list. -======= - * Returns an [ListBuffer] that wraps the original list. ->>>>>>> dev */ public fun MutableList.asMutableBuffer(): MutableListBuffer = MutableListBuffer(this) @@ -286,6 +282,24 @@ public class VirtualBuffer(override val size: Int, private val generator: (In override operator fun iterator(): Iterator = (0 until size).asSequence().map(generator).iterator() } +public class VirtualMutableBuffer(override val size: Int, private val generator: (Int) -> T) : MutableBuffer { + + private val bufferHolder: MutableListBuffer = (0 until size).map(generator).toMutableList().asMutableBuffer() + + override operator fun get(index: Int): T { + if (index < 0 || index >= size) throw IndexOutOfBoundsException("Expected index from 0 to ${size - 1}, but found $index") + return bufferHolder[index] + } + + override operator fun iterator(): Iterator = bufferHolder.iterator() + + override fun set(index: Int, value: T) { + bufferHolder[index] = value + } + + override fun copy(): MutableBuffer = bufferHolder.copy() +} + /** * Convert this buffer to read-only buffer. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt index 9f70f9621..54417e842 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -9,8 +9,8 @@ public interface TensorPartialDivisionAlgebra public operator fun TensorType.divAssign(other: TensorType) //https://pytorch.org/docs/stable/generated/torch.mean.html#torch.mean - public fun TensorType.mean(dim: Int, keepDim: Boolean): TensorType + public fun TensorType.mean(dim: Int = 0, keepDim: Boolean = false): TensorType //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var - public fun TensorType.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType + public fun TensorType.variance(dim: Int = 0, unbiased: Boolean = true, keepDim: Boolean = false): TensorType } From 1f19ac88aee34ed5b790356a81f762b21c1752f3 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 26 Mar 2021 17:43:08 +0300 Subject: [PATCH 140/393] qr fix --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 2 +- .../tensors/core/DoubleLinearOpsTensorAlgebra.kt | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index 3d1625a50..d980c510f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -14,7 +14,7 @@ public interface LinearOpsTensorAlgebra, Inde public fun TensorType.cholesky(): TensorType //https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr - public fun TensorType.qr(): TensorType + public fun TensorType.qr(): Pair //https://pytorch.org/docs/stable/generated/torch.lu.html public fun TensorType.lu(): Pair diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 0b9d824f0..d49fc941a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,8 +1,10 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.linear.Matrix import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.nd.Structure1D import space.kscience.kmath.nd.Structure2D +import space.kscience.kmath.nd.asND import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import kotlin.math.sqrt @@ -141,7 +143,15 @@ public class DoubleLinearOpsTensorAlgebra : return lTensor } - override fun DoubleTensor.qr(): DoubleTensor { + private fun matrixQR( + matrix: Structure2D, + q: MutableStructure2D, + r: MutableStructure2D + ) { + + } + + override fun DoubleTensor.qr(): Pair { TODO("ANDREI") } @@ -154,6 +164,7 @@ public class DoubleLinearOpsTensorAlgebra : } private fun luMatrixDet(lu: Structure2D, pivots: Structure1D): Double { + // todo check val m = lu.shape[0] val sign = if((pivots[m] - m) % 2 == 0) 1.0 else -1.0 return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } @@ -184,6 +195,7 @@ public class DoubleLinearOpsTensorAlgebra : pivots: Structure1D, invMatrix : MutableStructure2D ): Unit { + //todo check val m = lu.shape[0] for (j in 0 until m) { From a6354623ec08bb0c66d1e2a45eacde3b08e29c57 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 15:06:05 +0000 Subject: [PATCH 141/393] returning cols/rows as vectors --- kmath-core/api/kmath-core.api | 5 +++++ .../kotlin/space/kscience/kmath/nd/Structure1D.kt | 15 +++++++++++++++ .../kotlin/space/kscience/kmath/nd/Structure2D.kt | 8 ++++---- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index a109aaab5..0a3e3721d 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2768,6 +2768,11 @@ public abstract interface class space/kscience/kmath/tensors/TensorPartialDivisi public abstract fun variance (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; } +public final class space/kscience/kmath/tensors/TensorPartialDivisionAlgebra$DefaultImpls { + public static synthetic fun mean$default (Lspace/kscience/kmath/tensors/TensorPartialDivisionAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;IZILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; + public static synthetic fun variance$default (Lspace/kscience/kmath/tensors/TensorPartialDivisionAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;IZZILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; +} + public final class space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra { public fun ()V public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index c157f9a2f..354f3d802 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -71,6 +71,21 @@ private inline class Buffer1DWrapper(val buffer: Buffer) : Structure1D override operator fun get(index: Int): T = buffer[index] } +internal inline class MutableBuffer1DWrapper(val buffer: MutableBuffer) : MutableStructure1D { + override val shape: IntArray get() = intArrayOf(buffer.size) + override val size: Int get() = buffer.size + + override fun elements(): Sequence> = + buffer.asSequence().mapIndexed { index, value -> intArrayOf(index) to value } + + override operator fun get(index: Int): T = buffer[index] + override fun set(index: Int, value: T) { + buffer[index] = value + } + + override fun copy(): MutableBuffer = buffer.copy() +} + /** * Represent a [StructureND] as [Structure1D]. Throw error in case of dimension mismatch */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 762b59b28..e1a1d37de 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -75,14 +75,14 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { /** * The buffer of rows of this structure. It gets elements from the structure dynamically. */ - override val rows: List> - get() = List(rowNum) { i -> VirtualMutableBuffer(colNum) { j -> get(i, j) } } + override val rows: List> + get() = List(rowNum) { i -> MutableBuffer1DWrapper(VirtualMutableBuffer(colNum) { j -> get(i, j) })} /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ - override val columns: List> - get() = List(colNum) { j -> VirtualMutableBuffer(rowNum) { i -> get(i, j) } } + override val columns: List> + get() = List(colNum) { j -> MutableBuffer1DWrapper(VirtualMutableBuffer(rowNum) { i -> get(i, j) }) } } /** From 1588b5d94ff751fdf2d1d91686173068430723cd Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 15:09:18 +0000 Subject: [PATCH 142/393] once mutable stay it and enjoy --- .../kotlin/space/kscience/kmath/nd/Structure2D.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index e1a1d37de..8e41110fe 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -75,14 +75,14 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { /** * The buffer of rows of this structure. It gets elements from the structure dynamically. */ - override val rows: List> - get() = List(rowNum) { i -> MutableBuffer1DWrapper(VirtualMutableBuffer(colNum) { j -> get(i, j) })} + override val rows: MutableList> + get() = MutableList(rowNum) { i -> MutableBuffer1DWrapper(VirtualMutableBuffer(colNum) { j -> get(i, j) })} /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ - override val columns: List> - get() = List(colNum) { j -> MutableBuffer1DWrapper(VirtualMutableBuffer(rowNum) { i -> get(i, j) }) } + override val columns: MutableList> + get() = MutableList(colNum) { j -> MutableBuffer1DWrapper(VirtualMutableBuffer(rowNum) { i -> get(i, j) }) } } /** From e03910354e5ba02b6ec5551357ba629fa8cd8cca Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 15:14:23 +0000 Subject: [PATCH 143/393] ok reverting --- .../kotlin/space/kscience/kmath/nd/Structure2D.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 8e41110fe..e1a1d37de 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -75,14 +75,14 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { /** * The buffer of rows of this structure. It gets elements from the structure dynamically. */ - override val rows: MutableList> - get() = MutableList(rowNum) { i -> MutableBuffer1DWrapper(VirtualMutableBuffer(colNum) { j -> get(i, j) })} + override val rows: List> + get() = List(rowNum) { i -> MutableBuffer1DWrapper(VirtualMutableBuffer(colNum) { j -> get(i, j) })} /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ - override val columns: MutableList> - get() = MutableList(colNum) { j -> MutableBuffer1DWrapper(VirtualMutableBuffer(rowNum) { i -> get(i, j) }) } + override val columns: List> + get() = List(colNum) { j -> MutableBuffer1DWrapper(VirtualMutableBuffer(rowNum) { i -> get(i, j) }) } } /** From 516cd90677700d3f49096194bffa2cfd17ea78eb Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 15:36:53 +0000 Subject: [PATCH 144/393] Moved out to archive unimplemented API --- kmath-core/api/kmath-core.api | 160 +----------------- .../kmath/tensors/AnalyticTensorAlgebra.kt | 63 +------ .../kmath/tensors/ComplexTensorAlgebra.kt | 53 ------ .../kmath/tensors/ComplexTensorStructure.kt | 14 -- .../kmath/tensors/OrderedTensorAlgebra.kt | 29 ---- .../kscience/kmath/tensors/TensorAlgebra.kt | 26 --- .../tensors/TensorPartialDivisionAlgebra.kt | 6 - .../core/DoubleAnalyticTensorAlgebra.kt | 83 +-------- .../core/DoubleOrderedTensorAlgebra.kt | 43 ----- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 43 ----- 10 files changed, 4 insertions(+), 516 deletions(-) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 0a3e3721d..a45f00a55 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2619,7 +2619,7 @@ public final class space/kscience/kmath/structures/VirtualMutableBuffer : space/ public fun set (ILjava/lang/Object;)V } -public abstract interface class space/kscience/kmath/tensors/AnalyticTensorAlgebra : space/kscience/kmath/tensors/OrderedTensorAlgebra, space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { +public abstract interface class space/kscience/kmath/tensors/AnalyticTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { public abstract fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun acosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun asin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2627,59 +2627,16 @@ public abstract interface class space/kscience/kmath/tensors/AnalyticTensorAlgeb public abstract fun atan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun atanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun ceil (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun clamp (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun cos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun cosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun erf (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun erfc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun erfinv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun exp (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun floor (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun heaviside (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun histc (Lspace/kscience/kmath/nd/MutableStructureND;ILjava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun igamma (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun igammac (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun lerp (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun lgamma (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun log (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun logit (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun mvlgamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun polygamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun pow (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun quantile (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun round (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun sigmoid (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun sin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun sinc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun sinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun sqrt (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun std (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun tan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun tanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun trapz (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; -} - -public abstract interface class space/kscience/kmath/tensors/ComplexTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { - public abstract fun angle (Lspace/kscience/kmath/tensors/ComplexTensorStructure;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun bartlettWindow (IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun blackmanWindow (IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cartesianEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/tensors/ComplexTensorStructure; - public abstract fun hammingWindow (IZLjava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun inverseShortTimeFourierTransform (Lspace/kscience/kmath/tensors/ComplexTensorStructure;IIILspace/kscience/kmath/nd/MutableStructureND;ZZZI)V - public abstract fun kaiserWindow (IZLjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun polarEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/tensors/ComplexTensorStructure; - public abstract fun shortTimeFourierTransform (Lspace/kscience/kmath/tensors/ComplexTensorStructure;IIILspace/kscience/kmath/nd/MutableStructureND;ZZ)V - public abstract fun viewAsComplex (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/tensors/ComplexTensorStructure; -} - -public abstract interface class space/kscience/kmath/tensors/ComplexTensorStructure : space/kscience/kmath/nd/MutableStructureND { - public abstract fun imaginaryPart ()Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun realPart ()Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun viewAsReal ()Lspace/kscience/kmath/nd/MutableStructureND; -} - -public final class space/kscience/kmath/tensors/ComplexTensorStructure$DefaultImpls { - public static fun getDimension (Lspace/kscience/kmath/tensors/ComplexTensorStructure;)I } public abstract interface class space/kscience/kmath/tensors/LinearOpsTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { @@ -2697,32 +2654,16 @@ public final class space/kscience/kmath/tensors/LinearOpsTensorAlgebra$DefaultIm public static synthetic fun symEig$default (Lspace/kscience/kmath/tensors/LinearOpsTensorAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;ZILjava/lang/Object;)Lkotlin/Pair; } -public abstract interface class space/kscience/kmath/tensors/OrderedTensorAlgebra : space/kscience/kmath/tensors/TensorAlgebra { - public abstract fun cummax (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cummin (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun max (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun maximum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun median (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun min (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun minimum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun sort (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; -} - public abstract interface class space/kscience/kmath/tensors/ReduceOpsTensorAlgebra : space/kscience/kmath/tensors/TensorAlgebra { public abstract fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; } public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { - public abstract fun abs (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cat (Ljava/util/List;I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cumprod (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun eq (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Z public abstract fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun flatten (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun fullLike (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2738,10 +2679,6 @@ public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V public abstract fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun prod (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun square (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun squeeze (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun sum (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun times (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2764,13 +2701,6 @@ public abstract interface class space/kscience/kmath/tensors/TensorPartialDivisi public abstract fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V public abstract fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun mean (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun variance (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; -} - -public final class space/kscience/kmath/tensors/TensorPartialDivisionAlgebra$DefaultImpls { - public static synthetic fun mean$default (Lspace/kscience/kmath/tensors/TensorPartialDivisionAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;IZILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public static synthetic fun variance$default (Lspace/kscience/kmath/tensors/TensorPartialDivisionAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;IZZILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; } public final class space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra { @@ -2815,7 +2745,7 @@ public class space/kscience/kmath/tensors/core/BufferedTensor : space/kscience/k public final fun vectorSequence ()Lkotlin/sequences/Sequence; } -public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra : space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra, space/kscience/kmath/tensors/AnalyticTensorAlgebra { +public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/AnalyticTensorAlgebra { public fun ()V public synthetic fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun acos (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; @@ -2831,66 +2761,26 @@ public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra public fun atanh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun ceil (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun ceil (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun clamp (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun clamp (Lspace/kscience/kmath/tensors/core/DoubleTensor;DD)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun cos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun cos (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun cosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun cosh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun erf (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun erf (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun erfc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun erfc (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun erfinv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun erfinv (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun exp (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun exp (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun floor (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun floor (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun heaviside (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun heaviside (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun histc (Lspace/kscience/kmath/nd/MutableStructureND;ILjava/lang/Object;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun histc (Lspace/kscience/kmath/tensors/core/DoubleTensor;IDD)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun igamma (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun igamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun igammac (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun igammac (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun lerp (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun lerp (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun lgamma (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun lgamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun log (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun log (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun logit (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun logit (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun mvlgamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun mvlgamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun polygamma (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun polygamma (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun pow (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun pow (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun quantile (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun quantile (Lspace/kscience/kmath/tensors/core/DoubleTensor;DIZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun round (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun round (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun sigmoid (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sigmoid (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun sin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun sin (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun sinc (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sinc (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun sinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun sinh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun sqrt (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun sqrt (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun std (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun std (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun tan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun tan (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun tanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun tanh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun trapz (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun trapz (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; } public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebraKt { @@ -2923,30 +2813,6 @@ public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebr public static final fun DoubleLinearOpsTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } -public class space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/OrderedTensorAlgebra { - public fun ()V - public synthetic fun cummax (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cummax (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun cummin (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cummin (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun max (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun max (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun maximum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun maximum (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun median (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun median (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun min (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun min (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun minimum (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun minimum (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun sort (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sort (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; -} - -public final class space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebraKt { - public static final fun DoubleOrderedTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - public final class space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/ReduceOpsTensorAlgebra { public fun ()V public synthetic fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; @@ -2962,19 +2828,11 @@ public final class space/kscience/kmath/tensors/core/DoubleTensor : space/kscien public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { public fun ()V - public synthetic fun abs (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun abs (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun cat (Ljava/util/List;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cat (Ljava/util/List;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z public static synthetic fun contentEquals$default (Lspace/kscience/kmath/tensors/core/DoubleTensorAlgebra;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;DILjava/lang/Object;)Z public synthetic fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun copy (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun cumprod (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cumprod (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun cumsum (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cumsum (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public fun diagonalEmbedding (Lspace/kscience/kmath/tensors/core/DoubleTensor;III)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2993,8 +2851,6 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z public synthetic fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; public fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun flatten (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; - public fun flatten (Lspace/kscience/kmath/tensors/core/DoubleTensor;II)Lspace/kscience/kmath/tensors/core/DoubleTensor; public final fun fromArray ([I[D)Lspace/kscience/kmath/tensors/core/DoubleTensor; public fun full (D[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; @@ -3003,8 +2859,6 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public synthetic fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public fun get (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public final fun map (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun mean (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun mean (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; public fun minus (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -3029,14 +2883,6 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun prod (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun prod (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun square (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun square (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun squeeze (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun squeeze (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun sum (Lspace/kscience/kmath/nd/MutableStructureND;IZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sum (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; public fun times (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -3051,8 +2897,6 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public fun transpose (Lspace/kscience/kmath/tensors/core/DoubleTensor;II)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun unaryMinus (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun variance (Lspace/kscience/kmath/nd/MutableStructureND;IZZ)Lspace/kscience/kmath/nd/MutableStructureND; - public fun variance (Lspace/kscience/kmath/tensors/core/DoubleTensor;IZZ)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; public fun view (Lspace/kscience/kmath/tensors/core/DoubleTensor;[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt index c3a558298..fa1de81fa 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt @@ -2,14 +2,7 @@ package space.kscience.kmath.tensors public interface AnalyticTensorAlgebra> : - TensorPartialDivisionAlgebra, - OrderedTensorAlgebra{ - - //https://pytorch.org/docs/stable/generated/torch.quantile.html#torch.quantile - public fun TensorType.quantile(q: T, dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.std.html#torch.std - public fun TensorType.std(dim: Int, unbiased: Boolean, keepDim: Boolean): TensorType + TensorPartialDivisionAlgebra { //https://pytorch.org/docs/stable/generated/torch.exp.html public fun TensorType.exp(): TensorType @@ -62,58 +55,4 @@ public interface AnalyticTensorAlgebra> : //https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor public fun TensorType.floor(): TensorType - //https://pytorch.org/docs/stable/generated/torch.clamp.html#torch.clamp - public fun TensorType.clamp(min: T, max: T): TensorType - - //https://pytorch.org/docs/stable/generated/torch.erf.html#torch.erf - public fun TensorType.erf(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.erfinv.html#torch.erfinv - public fun TensorType.erfinv(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.erfc.html#torch.erfc - public fun TensorType.erfc(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.lerp.html#torch.lerp - public fun TensorType.lerp(end: TensorType, weight: TensorType): TensorType - - //https://pytorch.org/docs/stable/generated/torch.lgamma.html#torch.lgamma - public fun TensorType.lgamma(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.logit.html#torch.logit - public fun TensorType.logit(eps: T): TensorType - - //https://pytorch.org/docs/stable/generated/torch.igamma.html#torch.igamma - public fun TensorType.igamma(other: TensorType): TensorType - - //https://pytorch.org/docs/stable/generated/torch.igammac.html#torch.igammac - public fun TensorType.igammac(other: TensorType): TensorType - - //https://pytorch.org/docs/stable/generated/torch.mvlgamma.html#torch.mvlgamma - public fun TensorType.mvlgamma(dimensions: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.polygamma.html#torch.polygamma - public fun TensorType.polygamma(order: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.pow.html#torch.pow - public fun TensorType.pow(exponent: T): TensorType - - //https://pytorch.org/docs/stable/generated/torch.round.html#torch.round - public fun TensorType.round(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.sigmoid.html#torch.sigmoid - public fun TensorType.sigmoid(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.sinc.html#torch.sinc - public fun TensorType.sinc(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.heaviside.html#torch.heaviside - public fun TensorType.heaviside(values: TensorType): TensorType - - //https://pytorch.org/docs/stable/generated/torch.trapz.html#torch.trapz - public fun TensorType.trapz(xValues: TensorType, dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.histc.html#torch.histc - public fun TensorType.histc(bins: Int, min: T, max: T): TensorType - } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt deleted file mode 100644 index e56920916..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorAlgebra.kt +++ /dev/null @@ -1,53 +0,0 @@ -package space.kscience.kmath.tensors - -public interface ComplexTensorAlgebra, - ComplexTensorType : ComplexTensorStructure> - : TensorPartialDivisionAlgebra{ - - //https://pytorch.org/docs/stable/generated/torch.view_as_complex.html - public fun RealTensorType.viewAsComplex(): ComplexTensorType - - // Embed a real tensor as real + i * imaginary - public fun RealTensorType.cartesianEmbedding(imaginary: RealTensorType): ComplexTensorType - - // Embed a real tensor as real * exp(i * angle) - public fun RealTensorType.polarEmbedding(angle: RealTensorType): ComplexTensorType - - //https://pytorch.org/docs/stable/generated/torch.angle.html - public fun ComplexTensorType.angle(): RealTensorType - - //https://pytorch.org/docs/stable/generated/torch.stft.html#torch.stft - public fun ComplexTensorType.shortTimeFourierTransform( - nFFT: Int, - hopLength: Int, - winLength: Int, - window: RealTensorType, - normalised: Boolean, - oneSided: Boolean - ) - - //https://pytorch.org/docs/stable/generated/torch.istft.html#torch.istft - public fun ComplexTensorType.inverseShortTimeFourierTransform( - nFFT: Int, - hopLength: Int, - winLength: Int, - window: RealTensorType, - center: Boolean, - normalised: Boolean, - oneSided: Boolean, - length: Int - ) - - //https://pytorch.org/docs/stable/generated/torch.bartlett_window.html#torch.bartlett_window - public fun bartlettWindow(windowLength: Int, periodic: Boolean): RealTensorType - - //https://pytorch.org/docs/stable/generated/torch.blackman_window.html#torch.blackman_window - public fun blackmanWindow(windowLength: Int, periodic: Boolean): RealTensorType - - //https://pytorch.org/docs/stable/generated/torch.hamming_window.html#torch.hamming_window - public fun hammingWindow(windowLength: Int, periodic: Boolean, alpha: T, beta: T): RealTensorType - - //https://pytorch.org/docs/stable/generated/torch.kaiser_window.html#torch.kaiser_window - public fun kaiserWindow(windowLength: Int, periodic: Boolean, beta: T): RealTensorType -} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt deleted file mode 100644 index 0e0975830..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ComplexTensorStructure.kt +++ /dev/null @@ -1,14 +0,0 @@ -package space.kscience.kmath.tensors - -public interface ComplexTensorStructure> : TensorStructure { - - //https://pytorch.org/docs/master/generated/torch.view_as_real.html - public fun viewAsReal(): RealTensorType - - //https://pytorch.org/docs/stable/generated/torch.real.html - public fun realPart(): RealTensorType - - //https://pytorch.org/docs/stable/generated/torch.imag.html - public fun imaginaryPart(): RealTensorType - -} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt deleted file mode 100644 index 3320c3a1e..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/OrderedTensorAlgebra.kt +++ /dev/null @@ -1,29 +0,0 @@ -package space.kscience.kmath.tensors - -public interface OrderedTensorAlgebra> : - TensorAlgebra { - - //https://pytorch.org/docs/stable/generated/torch.max.html#torch.max - public fun TensorType.max(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.cummax.html#torch.cummax - public fun TensorType.cummax(dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.min.html#torch.min - public fun TensorType.min(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.cummin.html#torch.cummin - public fun TensorType.cummin(dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.median.html#torch.median - public fun TensorType.median(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.maximum.html#torch.maximum - public fun maximum(lhs: TensorType, rhs: TensorType) - - //https://pytorch.org/docs/stable/generated/torch.minimum.html#torch.minimum - public fun minimum(lhs: TensorType, rhs: TensorType) - - //https://pytorch.org/docs/stable/generated/torch.sort.html#torch.sort - public fun TensorType.sort(dim: Int, keepDim: Boolean, descending: Boolean): TensorType -} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 37c6a34f8..b05105ed8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -41,9 +41,6 @@ public interface TensorAlgebra> { public operator fun TensorType.timesAssign(other: TensorType): Unit public operator fun TensorType.unaryMinus(): TensorType - //https://pytorch.org/docs/stable/generated/torch.square.html - public fun TensorType.square(): TensorType - //https://pytorch.org/cppdocs/notes/tensor_indexing.html public operator fun TensorType.get(i: Int): TensorType @@ -56,21 +53,6 @@ public interface TensorAlgebra> { public fun TensorType.eq(other: TensorType, delta: T): Boolean - //https://pytorch.org/docs/stable/generated/torch.abs.html - public fun TensorType.abs(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.sum.html - public fun TensorType.sum(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.cumsum.html#torch.cumsum - public fun TensorType.cumsum(dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.prod.html#torch.prod - public fun TensorType.prod(dim: Int, keepDim: Boolean): TensorType - - //https://pytorch.org/docs/stable/generated/torch.cumprod.html#torch.cumprod - public fun TensorType.cumprod(dim: Int): TensorType - //https://pytorch.org/docs/stable/generated/torch.matmul.html public infix fun TensorType.dot(other: TensorType): TensorType @@ -80,12 +62,4 @@ public interface TensorAlgebra> { offset: Int = 0, dim1: Int = -2, dim2: Int = -1 ): TensorType - //https://pytorch.org/docs/stable/generated/torch.cat.html#torch.cat - public fun cat(tensors: List, dim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.flatten.html#torch.flatten - public fun TensorType.flatten(startDim: Int, endDim: Int): TensorType - - //https://pytorch.org/docs/stable/generated/torch.squeeze.html - public fun TensorType.squeeze(dim: Int): TensorType } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt index 54417e842..67b9c9d73 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -7,10 +7,4 @@ public interface TensorPartialDivisionAlgebra public operator fun TensorType.div(other: TensorType): TensorType public operator fun TensorType.divAssign(value: T) public operator fun TensorType.divAssign(other: TensorType) - - //https://pytorch.org/docs/stable/generated/torch.mean.html#torch.mean - public fun TensorType.mean(dim: Int = 0, keepDim: Boolean = false): TensorType - - //https://pytorch.org/docs/stable/generated/torch.var.html#torch.var - public fun TensorType.variance(dim: Int = 0, unbiased: Boolean = true, keepDim: Boolean = false): TensorType } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt index 1eb4c3b63..b46c7fa9c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt @@ -5,11 +5,10 @@ import kotlin.math.* public class DoubleAnalyticTensorAlgebra: AnalyticTensorAlgebra, - DoubleOrderedTensorAlgebra() + DoubleTensorAlgebra() { override fun DoubleTensor.exp(): DoubleTensor = this.map(::exp) - // todo log with other base???? override fun DoubleTensor.log(): DoubleTensor = this.map(::ln) override fun DoubleTensor.sqrt(): DoubleTensor = this.map(::sqrt) @@ -42,86 +41,6 @@ public class DoubleAnalyticTensorAlgebra: override fun DoubleTensor.floor(): DoubleTensor = this.map(::floor) - override fun DoubleTensor.clamp(min: Double, max: Double): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.erf(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.erfinv(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.erfc(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.lerp(end: DoubleTensor, weight: DoubleTensor): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.lgamma(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.logit(eps: Double): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.igamma(other: DoubleTensor): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.igammac(other: DoubleTensor): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.mvlgamma(dimensions: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.polygamma(order: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.pow(exponent: Double): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.round(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.sigmoid(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.sinc(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.heaviside(values: DoubleTensor): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.trapz(xValues: DoubleTensor, dim: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.quantile(q: Double, dim: Int, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.std(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.histc(bins: Int, min: Double, max: Double): DoubleTensor { - TODO("Not yet implemented") - } - } public inline fun DoubleAnalyticTensorAlgebra(block: DoubleAnalyticTensorAlgebra.() -> R): R = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt deleted file mode 100644 index a6bea59f4..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleOrderedTensorAlgebra.kt +++ /dev/null @@ -1,43 +0,0 @@ -package space.kscience.kmath.tensors.core - -import space.kscience.kmath.tensors.OrderedTensorAlgebra - -public open class DoubleOrderedTensorAlgebra: - OrderedTensorAlgebra, - DoubleTensorAlgebra() -{ - override fun DoubleTensor.max(dim: Int, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.cummax(dim: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.min(dim: Int, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.cummin(dim: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.median(dim: Int, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun maximum(lhs: DoubleTensor, rhs: DoubleTensor) { - TODO("Not yet implemented") - } - - override fun minimum(lhs: DoubleTensor, rhs: DoubleTensor) { - TODO("Not yet implemented") - } - - override fun DoubleTensor.sort(dim: Int, keepDim: Boolean, descending: Boolean): DoubleTensor { - TODO("Not yet implemented") - } -} - -public inline fun DoubleOrderedTensorAlgebra(block: DoubleOrderedTensorAlgebra.() -> R): R = - DoubleOrderedTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 0c82ec9c8..0a2e8c86c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -224,26 +224,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra, dim: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.flatten(startDim: Int, endDim: Int): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.mean(dim: Int, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.square(): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.variance(dim: Int, unbiased: Boolean, keepDim: Boolean): DoubleTensor { - TODO("Not yet implemented") - } - - override fun DoubleTensor.squeeze(dim: Int): DoubleTensor { - TODO("Not yet implemented") - } public fun DoubleTensor.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( From 22b68e5ca469038e8ee6c2083aafa2f54d51d032 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 26 Mar 2021 20:36:21 +0000 Subject: [PATCH 145/393] BufferedTensor2D & BufferedTensor1D --- kmath-core/api/kmath-core.api | 28 ++++ .../kmath/tensors/core/BufferedTensor.kt | 133 ++++++++++++++++-- .../core/DoubleLinearOpsTensorAlgebra.kt | 11 +- .../core/TestDoubleLinearOpsAlgebra.kt | 1 - .../kmath/tensors/core/TestDoubleTensor.kt | 3 - 5 files changed, 152 insertions(+), 24 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index a45f00a55..fc0905bd0 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2745,6 +2745,34 @@ public class space/kscience/kmath/tensors/core/BufferedTensor : space/kscience/k public final fun vectorSequence ()Lkotlin/sequences/Sequence; } +public final class space/kscience/kmath/tensors/core/BufferedTensor1D : space/kscience/kmath/tensors/core/BufferedTensor, space/kscience/kmath/nd/MutableStructure1D { + public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun get (I)Ljava/lang/Object; + public fun get ([I)Ljava/lang/Object; + public fun getDimension ()I + public fun getSize ()I + public fun iterator ()Ljava/util/Iterator; + public fun set (ILjava/lang/Object;)V + public fun set ([ILjava/lang/Object;)V +} + +public final class space/kscience/kmath/tensors/core/BufferedTensor2D : space/kscience/kmath/tensors/core/BufferedTensor, space/kscience/kmath/nd/MutableStructure2D { + public fun elements ()Lkotlin/sequences/Sequence; + public fun get (II)Ljava/lang/Object; + public fun get ([I)Ljava/lang/Object; + public fun getColNum ()I + public fun getColumns ()Ljava/util/List; + public fun getRowNum ()I + public fun getRows ()Ljava/util/List; + public fun getShape ()[I + public fun set (IILjava/lang/Object;)V +} + +public final class space/kscience/kmath/tensors/core/BufferedTensorKt { + public static final fun as1D (Lspace/kscience/kmath/tensors/core/BufferedTensor;)Lspace/kscience/kmath/tensors/core/BufferedTensor1D; + public static final fun as2D (Lspace/kscience/kmath/tensors/core/BufferedTensor;)Lspace/kscience/kmath/tensors/core/BufferedTensor2D; +} + public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/AnalyticTensorAlgebra { public fun ()V public synthetic fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 160c61260..aa6e58ef6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,23 +1,26 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.* +import space.kscience.kmath.nd.MutableStructure1D +import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.TensorStructure -import kotlin.math.atanh + public open class BufferedTensor( override val shape: IntArray, public val buffer: MutableBuffer, internal val bufferStart: Int -) : TensorStructure -{ +) : TensorStructure { public val linearStructure: TensorLinearStructure get() = TensorLinearStructure(shape) public val numel: Int get() = linearStructure.size + internal constructor(tensor: BufferedTensor) : + this(tensor.shape, tensor.buffer, tensor.bufferStart) + override fun get(index: IntArray): T = buffer[bufferStart + linearStructure.offset(index)] override fun set(index: IntArray, value: T) { @@ -32,8 +35,8 @@ public open class BufferedTensor( override fun hashCode(): Int = 0 - public fun vectorSequence(): Sequence> = sequence { - check(shape.size >= 1) {"todo"} + public fun vectorSequence(): Sequence> = sequence { + check(shape.size >= 1) { "todo" } val n = shape.size val vectorOffset = shape[n - 1] val vectorShape = intArrayOf(shape.last()) @@ -43,8 +46,8 @@ public open class BufferedTensor( } } - public fun matrixSequence(): Sequence> = sequence { - check(shape.size >= 2) {"todo"} + public fun matrixSequence(): Sequence> = sequence { + check(shape.size >= 2) { "todo" } val n = shape.size val matrixOffset = shape[n - 1] * shape[n - 2] val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) //todo better way? @@ -54,14 +57,14 @@ public open class BufferedTensor( } } - public inline fun forEachVector(vectorAction : (MutableStructure1D) -> Unit): Unit { - for (vector in vectorSequence()){ + public inline fun forEachVector(vectorAction: (BufferedTensor1D) -> Unit): Unit { + for (vector in vectorSequence()) { vectorAction(vector) } } - public inline fun forEachMatrix(matrixAction : (MutableStructure2D) -> Unit): Unit { - for (matrix in matrixSequence()){ + public inline fun forEachMatrix(matrixAction: (BufferedTensor2D) -> Unit): Unit { + for (matrix in matrixSequence()) { matrixAction(matrix) } } @@ -74,21 +77,125 @@ public class IntTensor internal constructor( buffer: IntArray, offset: Int = 0 ) : BufferedTensor(shape, IntBuffer(buffer), offset) +{ + internal constructor(bufferedTensor: BufferedTensor): + this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) +} public class LongTensor internal constructor( shape: IntArray, buffer: LongArray, offset: Int = 0 ) : BufferedTensor(shape, LongBuffer(buffer), offset) +{ + internal constructor(bufferedTensor: BufferedTensor): + this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) +} public class FloatTensor internal constructor( shape: IntArray, buffer: FloatArray, offset: Int = 0 ) : BufferedTensor(shape, FloatBuffer(buffer), offset) +{ + internal constructor(bufferedTensor: BufferedTensor): + this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) +} public class DoubleTensor internal constructor( shape: IntArray, buffer: DoubleArray, offset: Int = 0 -) : BufferedTensor(shape, DoubleBuffer(buffer), offset) \ No newline at end of file +) : BufferedTensor(shape, DoubleBuffer(buffer), offset) +{ + internal constructor(bufferedTensor: BufferedTensor): + this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) +} + + +public class BufferedTensor2D internal constructor( + private val tensor: BufferedTensor, +) : BufferedTensor(tensor), MutableStructure2D { + init { + check(shape.size == 2) { + "Shape ${shape.toList()} not compatible with DoubleTensor2D" + } + } + + override val shape: IntArray + get() = tensor.shape + + override val rowNum: Int + get() = shape[0] + override val colNum: Int + get() = shape[1] + + override fun get(i: Int, j: Int): T = tensor[intArrayOf(i, j)] + + override fun get(index: IntArray): T = tensor[index] + + override fun elements(): Sequence> = tensor.elements() + + override fun set(i: Int, j: Int, value: T) { + tensor[intArrayOf(i, j)] = value + } + + override val rows: List> + get() = List(rowNum) { i -> + BufferedTensor1D( + BufferedTensor( + shape = intArrayOf(colNum), + buffer = VirtualMutableBuffer(colNum) { j -> get(i, j) }, + bufferStart = 0 + ) + ) + } + + override val columns: List> + get() = List(colNum) { j -> + BufferedTensor1D( + BufferedTensor( + shape = intArrayOf(rowNum), + buffer = VirtualMutableBuffer(rowNum) { i -> get(i, j) }, + bufferStart = 0 + ) + ) + } +} + +public class BufferedTensor1D internal constructor( + private val tensor: BufferedTensor +) : BufferedTensor(tensor), MutableStructure1D { + init { + check(shape.size == 1) { + "Shape ${shape.toList()} not compatible with DoubleTensor1D" + } + } + + override fun get(index: IntArray): T = tensor[index] + + override fun set(index: IntArray, value: T) { + tensor[index] = value + } + + override val size: Int + get() = tensor.linearStructure.size + + override fun get(index: Int): T = tensor[intArrayOf(index)] + + override fun set(index: Int, value: T) { + tensor[intArrayOf(index)] = value + } + + override fun copy(): MutableBuffer = tensor.buffer.copy() + +} + +internal fun BufferedTensor.asIntTensor(): IntTensor = IntTensor(this) +internal fun BufferedTensor.asLongTensor(): LongTensor = LongTensor(this) +internal fun BufferedTensor.asFloatTensor(): FloatTensor = FloatTensor(this) +internal fun BufferedTensor.asDoubleTensor(): DoubleTensor = DoubleTensor(this) + + +public fun BufferedTensor.as2D(): BufferedTensor2D = BufferedTensor2D(this) +public fun BufferedTensor.as1D(): BufferedTensor1D = BufferedTensor1D(this) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 0b9d824f0..70fe8a1cc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,8 +1,5 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.MutableStructure2D -import space.kscience.kmath.nd.Structure1D -import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import kotlin.math.sqrt @@ -153,7 +150,7 @@ public class DoubleLinearOpsTensorAlgebra : TODO("ANDREI") } - private fun luMatrixDet(lu: Structure2D, pivots: Structure1D): Double { + private fun luMatrixDet(lu: BufferedTensor2D, pivots: BufferedTensor1D): Double { val m = lu.shape[0] val sign = if((pivots[m] - m) % 2 == 0) 1.0 else -1.0 return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } @@ -180,9 +177,9 @@ public class DoubleLinearOpsTensorAlgebra : } private fun luMatrixInv( - lu: Structure2D, - pivots: Structure1D, - invMatrix : MutableStructure2D + lu: BufferedTensor2D, + pivots: BufferedTensor1D, + invMatrix : BufferedTensor2D ): Unit { val m = lu.shape[0] diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index d77f33f9d..3a129b03c 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -1,7 +1,6 @@ package space.kscience.kmath.tensors.core import kotlin.math.abs -import kotlin.math.exp import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index b12b08b52..40597f539 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,8 +1,5 @@ package space.kscience.kmath.tensors.core - -import space.kscience.kmath.nd.as1D -import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray import kotlin.test.Test import kotlin.test.assertEquals From 92710097f06d0ec6161e4f3518a2fd0815ff157a Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 29 Mar 2021 21:58:56 +0100 Subject: [PATCH 146/393] Fixing 2D and 1D casts --- kmath-core/api/kmath-core.api | 33 --- .../kmath/tensors/core/BufferedTensor.kt | 107 +-------- .../core/DoubleLinearOpsTensorAlgebra.kt | 220 ++++++++++-------- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 53 +++-- .../kscience/kmath/tensors/core/checks.kt | 6 +- .../kmath/tensors/core/TestDoubleTensor.kt | 2 + 6 files changed, 173 insertions(+), 248 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index fc0905bd0..786b81d19 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2731,8 +2731,6 @@ public class space/kscience/kmath/tensors/core/BufferedTensor : space/kscience/k public fun ([ILspace/kscience/kmath/structures/MutableBuffer;I)V public fun elements ()Lkotlin/sequences/Sequence; public fun equals (Ljava/lang/Object;)Z - public final fun forEachMatrix (Lkotlin/jvm/functions/Function1;)V - public final fun forEachVector (Lkotlin/jvm/functions/Function1;)V public fun get ([I)Ljava/lang/Object; public final fun getBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; public fun getDimension ()I @@ -2740,37 +2738,7 @@ public class space/kscience/kmath/tensors/core/BufferedTensor : space/kscience/k public final fun getNumel ()I public fun getShape ()[I public fun hashCode ()I - public final fun matrixSequence ()Lkotlin/sequences/Sequence; public fun set ([ILjava/lang/Object;)V - public final fun vectorSequence ()Lkotlin/sequences/Sequence; -} - -public final class space/kscience/kmath/tensors/core/BufferedTensor1D : space/kscience/kmath/tensors/core/BufferedTensor, space/kscience/kmath/nd/MutableStructure1D { - public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; - public fun get (I)Ljava/lang/Object; - public fun get ([I)Ljava/lang/Object; - public fun getDimension ()I - public fun getSize ()I - public fun iterator ()Ljava/util/Iterator; - public fun set (ILjava/lang/Object;)V - public fun set ([ILjava/lang/Object;)V -} - -public final class space/kscience/kmath/tensors/core/BufferedTensor2D : space/kscience/kmath/tensors/core/BufferedTensor, space/kscience/kmath/nd/MutableStructure2D { - public fun elements ()Lkotlin/sequences/Sequence; - public fun get (II)Ljava/lang/Object; - public fun get ([I)Ljava/lang/Object; - public fun getColNum ()I - public fun getColumns ()Ljava/util/List; - public fun getRowNum ()I - public fun getRows ()Ljava/util/List; - public fun getShape ()[I - public fun set (IILjava/lang/Object;)V -} - -public final class space/kscience/kmath/tensors/core/BufferedTensorKt { - public static final fun as1D (Lspace/kscience/kmath/tensors/core/BufferedTensor;)Lspace/kscience/kmath/tensors/core/BufferedTensor1D; - public static final fun as2D (Lspace/kscience/kmath/tensors/core/BufferedTensor;)Lspace/kscience/kmath/tensors/core/BufferedTensor2D; } public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/AnalyticTensorAlgebra { @@ -2876,7 +2844,6 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public synthetic fun eq (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Z public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Z public fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z - public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z public synthetic fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; public fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public final fun fromArray ([I[D)Lspace/kscience/kmath/tensors/core/DoubleTensor; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index aa6e58ef6..d99c35569 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -35,35 +35,34 @@ public open class BufferedTensor( override fun hashCode(): Int = 0 - public fun vectorSequence(): Sequence> = sequence { - check(shape.size >= 1) { "todo" } + internal fun vectorSequence(): Sequence> = sequence { val n = shape.size val vectorOffset = shape[n - 1] val vectorShape = intArrayOf(shape.last()) for (offset in 0 until numel step vectorOffset) { - val vector = BufferedTensor(vectorShape, buffer, offset).as1D() + val vector = BufferedTensor(vectorShape, buffer, offset) yield(vector) } } - public fun matrixSequence(): Sequence> = sequence { + internal fun matrixSequence(): Sequence> = sequence { check(shape.size >= 2) { "todo" } val n = shape.size val matrixOffset = shape[n - 1] * shape[n - 2] - val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) //todo better way? + val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) for (offset in 0 until numel step matrixOffset) { - val matrix = BufferedTensor(matrixShape, buffer, offset).as2D() + val matrix = BufferedTensor(matrixShape, buffer, offset) yield(matrix) } } - public inline fun forEachVector(vectorAction: (BufferedTensor1D) -> Unit): Unit { + internal inline fun forEachVector(vectorAction: (BufferedTensor) -> Unit): Unit { for (vector in vectorSequence()) { vectorAction(vector) } } - public inline fun forEachMatrix(matrixAction: (BufferedTensor2D) -> Unit): Unit { + internal inline fun forEachMatrix(matrixAction: (BufferedTensor) -> Unit): Unit { for (matrix in matrixSequence()) { matrixAction(matrix) } @@ -71,7 +70,6 @@ public open class BufferedTensor( } - public class IntTensor internal constructor( shape: IntArray, buffer: IntArray, @@ -112,90 +110,7 @@ public class DoubleTensor internal constructor( this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) } - -public class BufferedTensor2D internal constructor( - private val tensor: BufferedTensor, -) : BufferedTensor(tensor), MutableStructure2D { - init { - check(shape.size == 2) { - "Shape ${shape.toList()} not compatible with DoubleTensor2D" - } - } - - override val shape: IntArray - get() = tensor.shape - - override val rowNum: Int - get() = shape[0] - override val colNum: Int - get() = shape[1] - - override fun get(i: Int, j: Int): T = tensor[intArrayOf(i, j)] - - override fun get(index: IntArray): T = tensor[index] - - override fun elements(): Sequence> = tensor.elements() - - override fun set(i: Int, j: Int, value: T) { - tensor[intArrayOf(i, j)] = value - } - - override val rows: List> - get() = List(rowNum) { i -> - BufferedTensor1D( - BufferedTensor( - shape = intArrayOf(colNum), - buffer = VirtualMutableBuffer(colNum) { j -> get(i, j) }, - bufferStart = 0 - ) - ) - } - - override val columns: List> - get() = List(colNum) { j -> - BufferedTensor1D( - BufferedTensor( - shape = intArrayOf(rowNum), - buffer = VirtualMutableBuffer(rowNum) { i -> get(i, j) }, - bufferStart = 0 - ) - ) - } -} - -public class BufferedTensor1D internal constructor( - private val tensor: BufferedTensor -) : BufferedTensor(tensor), MutableStructure1D { - init { - check(shape.size == 1) { - "Shape ${shape.toList()} not compatible with DoubleTensor1D" - } - } - - override fun get(index: IntArray): T = tensor[index] - - override fun set(index: IntArray, value: T) { - tensor[index] = value - } - - override val size: Int - get() = tensor.linearStructure.size - - override fun get(index: Int): T = tensor[intArrayOf(index)] - - override fun set(index: Int, value: T) { - tensor[intArrayOf(index)] = value - } - - override fun copy(): MutableBuffer = tensor.buffer.copy() - -} - -internal fun BufferedTensor.asIntTensor(): IntTensor = IntTensor(this) -internal fun BufferedTensor.asLongTensor(): LongTensor = LongTensor(this) -internal fun BufferedTensor.asFloatTensor(): FloatTensor = FloatTensor(this) -internal fun BufferedTensor.asDoubleTensor(): DoubleTensor = DoubleTensor(this) - - -public fun BufferedTensor.as2D(): BufferedTensor2D = BufferedTensor2D(this) -public fun BufferedTensor.as1D(): BufferedTensor1D = BufferedTensor1D(this) \ No newline at end of file +internal fun BufferedTensor.asTensor(): IntTensor = IntTensor(this) +internal fun BufferedTensor.asTensor(): LongTensor = LongTensor(this) +internal fun BufferedTensor.asTensor(): FloatTensor = FloatTensor(this) +internal fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 70fe8a1cc..0d19fd3f6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,5 +1,9 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.MutableStructure1D +import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.nd.as1D +import space.kscience.kmath.nd.as2D import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import kotlin.math.sqrt @@ -11,6 +15,48 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.det(): DoubleTensor = detLU() + private inline fun luHelper(lu: MutableStructure2D, pivots: MutableStructure1D, m: Int) { + for (row in 0 until m) pivots[row] = row + + for (i in 0 until m) { + var maxVal = -1.0 + var maxInd = i + + for (k in i until m) { + val absA = kotlin.math.abs(lu[k, i]) + if (absA > maxVal) { + maxVal = absA + maxInd = k + } + } + + //todo check singularity + + if (maxInd != i) { + + val j = pivots[i] + pivots[i] = pivots[maxInd] + pivots[maxInd] = j + + for (k in 0 until m) { + val tmp = lu[i, k] + lu[i, k] = lu[maxInd, k] + lu[maxInd, k] = tmp + } + + pivots[m] += 1 + + } + + for (j in i + 1 until m) { + lu[j, i] /= lu[i, i] + for (k in i + 1 until m) { + lu[j, k] -= lu[j, i] * lu[i, k] + } + } + } + } + override fun DoubleTensor.lu(): Pair { checkSquareMatrix(shape) @@ -27,90 +73,93 @@ public class DoubleLinearOpsTensorAlgebra : IntArray(pivotsShape.reduce(Int::times)) { 0 } ) - for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())){ - for (row in 0 until m) pivots[row] = row - - for (i in 0 until m) { - var maxVal = -1.0 - var maxInd = i - - for (k in i until m) { - val absA = kotlin.math.abs(lu[k, i]) - if (absA > maxVal) { - maxVal = absA - maxInd = k - } - } - - //todo check singularity - - if (maxInd != i) { - - val j = pivots[i] - pivots[i] = pivots[maxInd] - pivots[maxInd] = j - - for (k in 0 until m) { - val tmp = lu[i, k] - lu[i, k] = lu[maxInd, k] - lu[maxInd, k] = tmp - } - - pivots[m] += 1 - - } - - for (j in i + 1 until m) { - lu[j, i] /= lu[i, i] - for (k in i + 1 until m) { - lu[j, k] -= lu[j, i] * lu[i, k] - } - } - } - } - + for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) + luHelper(lu.as2D(), pivots.as1D(), m) return Pair(luTensor, pivotsTensor) } - override fun luPivot(luTensor: DoubleTensor, pivotsTensor: IntTensor): Triple { + private inline fun pivInit( + p: MutableStructure2D, + pivot: MutableStructure1D, + n: Int + ) { + for (i in 0 until n) { + p[i, pivot[i]] = 1.0 + } + } + + private inline fun luPivotHelper( + l: MutableStructure2D, + u: MutableStructure2D, + lu: MutableStructure2D, + n: Int + ) { + for (i in 0 until n) { + for (j in 0 until n) { + if (i == j) { + l[i, j] = 1.0 + } + if (j < i) { + l[i, j] = lu[i, j] + } + if (j >= i) { + u[i, j] = lu[i, j] + } + } + } + } + + override fun luPivot( + luTensor: DoubleTensor, + pivotsTensor: IntTensor + ): Triple { //todo checks checkSquareMatrix(luTensor.shape) - check(luTensor.shape.dropLast(1).toIntArray() contentEquals pivotsTensor.shape) { "Bed shapes (("} //todo rewrite + check( + luTensor.shape.dropLast(1).toIntArray() contentEquals pivotsTensor.shape + ) { "Bed shapes ((" } //todo rewrite val n = luTensor.shape.last() val pTensor = luTensor.zeroesLike() - for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.vectorSequence())){ - for (i in 0 until n){ - p[i, pivot[i]] = 1.0 - } - } + for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) + pivInit(p.as2D(), pivot.as1D(), n) val lTensor = luTensor.zeroesLike() val uTensor = luTensor.zeroesLike() - for ((pairLU, lu) in lTensor.matrixSequence().zip(uTensor.matrixSequence()).zip(luTensor.matrixSequence())){ + for ((pairLU, lu) in lTensor.matrixSequence().zip(uTensor.matrixSequence()) + .zip(luTensor.matrixSequence())) { val (l, u) = pairLU - for (i in 0 until n) { - for (j in 0 until n) { - if (i == j) { - l[i, j] = 1.0 - } - if (j < i) { - l[i, j] = lu[i, j] - } - if (j >= i) { - u[i, j] = lu[i, j] - } - } - } + luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) } return Triple(pTensor, lTensor, uTensor) } + private inline fun choleskyHelper( + a: MutableStructure2D, + l: MutableStructure2D, + n: Int + ) { + for (i in 0 until n) { + for (j in 0 until i) { + var h = a[i, j] + for (k in 0 until j) { + h -= l[i, k] * l[j, k] + } + l[i, j] = h / l[j, j] + } + var h = a[i, i] + for (j in 0 until i) { + h -= l[i, j] * l[i, j] + } + l[i, i] = sqrt(h) + } + } + override fun DoubleTensor.cholesky(): DoubleTensor { // todo checks checkSquareMatrix(shape) @@ -118,22 +167,8 @@ public class DoubleLinearOpsTensorAlgebra : val n = shape.last() val lTensor = zeroesLike() - for ((a, l) in this.matrixSequence().zip(lTensor.matrixSequence())) { - for (i in 0 until n) { - for (j in 0 until i) { - var h = a[i, j] - for (k in 0 until j) { - h -= l[i, k] * l[j, k] - } - l[i, j] = h / l[j, j] - } - var h = a[i, i] - for (j in 0 until i) { - h -= l[i, j] * l[i, j] - } - l[i, i] = sqrt(h) - } - } + for ((a, l) in this.matrixSequence().zip(lTensor.matrixSequence())) + for (i in 0 until n) choleskyHelper(a.as2D(), l.as2D(), n) return lTensor } @@ -150,9 +185,11 @@ public class DoubleLinearOpsTensorAlgebra : TODO("ANDREI") } - private fun luMatrixDet(lu: BufferedTensor2D, pivots: BufferedTensor1D): Double { + private fun luMatrixDet(luTensor: MutableStructure2D, pivotsTensor: MutableStructure1D): Double { + val lu = luTensor.as2D() + val pivots = pivotsTensor.as1D() val m = lu.shape[0] - val sign = if((pivots[m] - m) % 2 == 0) 1.0 else -1.0 + val sign = if ((pivots[m] - m) % 2 == 0) 1.0 else -1.0 return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } } @@ -162,34 +199,34 @@ public class DoubleLinearOpsTensorAlgebra : val detTensorShape = IntArray(n - 1) { i -> shape[i] } detTensorShape[n - 2] = 1 - val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } + val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } val detTensor = DoubleTensor( detTensorShape, resBuffer ) - luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (luMatrix, pivots) -> - resBuffer[index] = luMatrixDet(luMatrix, pivots) + luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (lu, pivots) -> + resBuffer[index] = luMatrixDet(lu.as2D(), pivots.as1D()) } return detTensor } private fun luMatrixInv( - lu: BufferedTensor2D, - pivots: BufferedTensor1D, - invMatrix : BufferedTensor2D - ): Unit { + lu: MutableStructure2D, + pivots: MutableStructure1D, + invMatrix: MutableStructure2D + ) { val m = lu.shape[0] for (j in 0 until m) { for (i in 0 until m) { - if (pivots[i] == j){ + if (pivots[i] == j) { invMatrix[i, j] = 1.0 } - for (k in 0 until i){ + for (k in 0 until i) { invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] } } @@ -205,13 +242,12 @@ public class DoubleLinearOpsTensorAlgebra : public fun DoubleTensor.invLU(): DoubleTensor { val (luTensor, pivotsTensor) = lu() - val n = shape.size val invTensor = luTensor.zeroesLike() val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) for ((luP, invMatrix) in seq) { val (lu, pivots) = luP - luMatrixInv(lu, pivots, invMatrix) + luMatrixInv(lu.as2D(), pivots.as1D(), invMatrix.as2D()) } return invTensor diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 0a2e8c86c..b25f0164b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,8 +1,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.linear.Matrix import space.kscience.kmath.nd.MutableStructure2D -import space.kscience.kmath.nd.Structure2D +import space.kscience.kmath.nd.as2D import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra import kotlin.math.abs @@ -224,6 +223,23 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra, + b: MutableStructure2D, + res: MutableStructure2D, + l: Int, m: Int, n: Int + ) { + for (i in 0 until l) { + for (j in 0 until n) { + var curr = 0.0 + for (k in 0 until m) { + curr += a[i, k] * b[k, j] + } + res[i, j] = curr + } + } + } + override fun DoubleTensor.dot(other: DoubleTensor): DoubleTensor { if (this.shape.size == 1 && other.shape.size == 1) { return DoubleTensor(intArrayOf(1), doubleArrayOf(this.times(other).buffer.array().sum())) @@ -240,7 +256,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Boolean): Boolean { - if (!(this.shape contentEquals other.shape)) { - return false - } - return this.eq(other, eqFunction) - } + public fun DoubleTensor.contentEquals(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean = + this.eq(other, eqFunction) - public fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { - // todo broadcasting checking + private fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { + checkShapesCompatible(this, other) val n = this.linearStructure.size if (n != other.linearStructure.size) { return false diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index c644a295c..247ed3913 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -11,14 +11,14 @@ internal inline fun , "Illegal empty shape provided" } -internal inline fun < TensorType : TensorStructure, +internal inline fun , TorchTensorAlgebraType : TensorAlgebra> TorchTensorAlgebraType.checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = check(buffer.isNotEmpty()) { "Illegal empty buffer provided" } -internal inline fun < TensorType : TensorStructure, +internal inline fun , TorchTensorAlgebraType : TensorAlgebra> TorchTensorAlgebraType.checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = check(buffer.size == shape.reduce(Int::times)) { @@ -56,4 +56,4 @@ internal inline fun , check(shape[n - 1] == shape[n - 2]) { "Tensor must be batches of square matrices, but they are ${shape[n - 1]} by ${shape[n - 1]} matrices" } -} +} \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 40597f539..5e6fdcdc5 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.as1D +import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray import kotlin.test.Test import kotlin.test.assertEquals From 51eca003af9daeb72a53fc05867d955d1167154c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 29 Mar 2021 22:11:34 +0100 Subject: [PATCH 147/393] Moved back value to main algebra context --- kmath-core/api/kmath-core.api | 17 +++-------------- .../kmath/tensors/ReduceOpsTensorAlgebra.kt | 7 ------- .../kscience/kmath/tensors/TensorAlgebra.kt | 2 ++ .../core/DoubleReduceOpsTensorAlgebra.kt | 18 ------------------ .../kmath/tensors/core/DoubleTensorAlgebra.kt | 7 +++++++ .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 9 +++------ .../kmath/tensors/core/TestDoubleTensor.kt | 10 +++++++++- 7 files changed, 24 insertions(+), 46 deletions(-) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ReduceOpsTensorAlgebra.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 786b81d19..373920204 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2654,10 +2654,6 @@ public final class space/kscience/kmath/tensors/LinearOpsTensorAlgebra$DefaultIm public static synthetic fun symEig$default (Lspace/kscience/kmath/tensors/LinearOpsTensorAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;ZILjava/lang/Object;)Lkotlin/Pair; } -public abstract interface class space/kscience/kmath/tensors/ReduceOpsTensorAlgebra : space/kscience/kmath/tensors/TensorAlgebra { - public abstract fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; -} - public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { public abstract fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2686,6 +2682,7 @@ public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { public abstract fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V public abstract fun transpose (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; public abstract fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun zeroesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2809,16 +2806,6 @@ public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebr public static final fun DoubleLinearOpsTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } -public final class space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/ReduceOpsTensorAlgebra { - public fun ()V - public synthetic fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; - public fun value (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Ljava/lang/Double; -} - -public final class space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebraKt { - public static final fun DoubleReduceOpsTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - public final class space/kscience/kmath/tensors/core/DoubleTensor : space/kscience/kmath/tensors/core/BufferedTensor { } @@ -2892,6 +2879,8 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public fun transpose (Lspace/kscience/kmath/tensors/core/DoubleTensor;II)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun unaryMinus (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; + public fun value (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Ljava/lang/Double; public synthetic fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; public fun view (Lspace/kscience/kmath/tensors/core/DoubleTensor;[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ReduceOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ReduceOpsTensorAlgebra.kt deleted file mode 100644 index 820b9b25b..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/ReduceOpsTensorAlgebra.kt +++ /dev/null @@ -1,7 +0,0 @@ -package space.kscience.kmath.tensors - -public interface ReduceOpsTensorAlgebra> : - TensorAlgebra { - public fun TensorType.value(): T - -} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index b05105ed8..5b7515b20 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -5,6 +5,8 @@ import space.kscience.kmath.tensors.core.DoubleTensor // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { + public fun TensorType.value(): T + //https://pytorch.org/docs/stable/generated/torch.full.html public fun full(value: T, shape: IntArray): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt deleted file mode 100644 index 9a8aa9ebf..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleReduceOpsTensorAlgebra.kt +++ /dev/null @@ -1,18 +0,0 @@ -package space.kscience.kmath.tensors.core - -import space.kscience.kmath.tensors.ReduceOpsTensorAlgebra - -public class DoubleReduceOpsTensorAlgebra: - DoubleTensorAlgebra(), - ReduceOpsTensorAlgebra { - - override fun DoubleTensor.value(): Double { - check(this.shape contentEquals intArrayOf(1)) { - "Inconsistent value for tensor of shape ${shape.toList()}" - } - return this.buffer.array()[this.bufferStart] - } -} - -public inline fun DoubleReduceOpsTensorAlgebra(block: DoubleReduceOpsTensorAlgebra.() -> R): R = - DoubleReduceOpsTensorAlgebra().block() \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index b25f0164b..b418f3647 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -7,6 +7,13 @@ import kotlin.math.abs public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { + override fun DoubleTensor.value(): Double { + check(this.shape contentEquals intArrayOf(1)) { + "Inconsistent value for tensor of shape ${shape.toList()}" + } + return this.buffer.array()[this.bufferStart] + } + public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor { checkEmptyShape(shape) checkEmptyDoubleBuffer(buffer) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 3a129b03c..d2d4ffb67 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -72,11 +72,8 @@ class TestDoubleLinearOpsTensorAlgebra { @Test fun testScalarProduct() = DoubleLinearOpsTensorAlgebra { - val a = fromArray(intArrayOf(3), doubleArrayOf(1.8,2.5, 6.8)) - val b = fromArray(intArrayOf(3), doubleArrayOf(5.5,2.6, 6.4)) - DoubleReduceOpsTensorAlgebra { - assertEquals(a.dot(b).value(), 59.92) - } - + val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) + val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) + assertEquals(a.dot(b).value(), 59.92) } } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 5e6fdcdc5..4f4d9bbdf 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -10,7 +10,7 @@ import kotlin.test.assertTrue class TestDoubleTensor { @Test - fun valueTest() = DoubleReduceOpsTensorAlgebra { + fun valueTest() = DoubleTensorAlgebra { val value = 12.5 val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) @@ -37,5 +37,13 @@ class TestDoubleTensor { vector[0] = 109.56 assertEquals(tensor[intArrayOf(0,1,0)], 109.56) + + tensor.matrixSequence().forEach { + val a = it.asTensor() + val secondRow = a[1].as1D() + val secondColumn = a.transpose(0,1)[1].as1D() + assertEquals(secondColumn[0], 77.89) + assertEquals(secondRow[1], secondColumn[1]) + } } } \ No newline at end of file From d281dfca3ab869fcfb16181f82cc91b57bb4d26d Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 30 Mar 2021 11:22:55 +0100 Subject: [PATCH 148/393] Separate linear algebra utils into dedicated module --- .../kmath/tensors/core/BufferedTensor.kt | 38 ---- .../core/DoubleLinearOpsTensorAlgebra.kt | 134 +------------ .../kmath/tensors/core/DoubleTensorAlgebra.kt | 20 +- .../kscience/kmath/tensors/core/linutils.kt | 188 ++++++++++++++++++ 4 files changed, 190 insertions(+), 190 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index d99c35569..9a4d13d2c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,7 +1,5 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.MutableStructure1D -import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.TensorStructure @@ -18,9 +16,6 @@ public open class BufferedTensor( public val numel: Int get() = linearStructure.size - internal constructor(tensor: BufferedTensor) : - this(tensor.shape, tensor.buffer, tensor.bufferStart) - override fun get(index: IntArray): T = buffer[bufferStart + linearStructure.offset(index)] override fun set(index: IntArray, value: T) { @@ -35,39 +30,6 @@ public open class BufferedTensor( override fun hashCode(): Int = 0 - internal fun vectorSequence(): Sequence> = sequence { - val n = shape.size - val vectorOffset = shape[n - 1] - val vectorShape = intArrayOf(shape.last()) - for (offset in 0 until numel step vectorOffset) { - val vector = BufferedTensor(vectorShape, buffer, offset) - yield(vector) - } - } - - internal fun matrixSequence(): Sequence> = sequence { - check(shape.size >= 2) { "todo" } - val n = shape.size - val matrixOffset = shape[n - 1] * shape[n - 2] - val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) - for (offset in 0 until numel step matrixOffset) { - val matrix = BufferedTensor(matrixShape, buffer, offset) - yield(matrix) - } - } - - internal inline fun forEachVector(vectorAction: (BufferedTensor) -> Unit): Unit { - for (vector in vectorSequence()) { - vectorAction(vector) - } - } - - internal inline fun forEachMatrix(matrixAction: (BufferedTensor) -> Unit): Unit { - for (matrix in matrixSequence()) { - matrixAction(matrix) - } - } - } public class IntTensor internal constructor( diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 0d19fd3f6..b81cf0364 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -1,11 +1,8 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.MutableStructure1D -import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D -import space.kscience.kmath.tensors.LinearOpsTensorAlgebra -import kotlin.math.sqrt public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -15,48 +12,6 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.det(): DoubleTensor = detLU() - private inline fun luHelper(lu: MutableStructure2D, pivots: MutableStructure1D, m: Int) { - for (row in 0 until m) pivots[row] = row - - for (i in 0 until m) { - var maxVal = -1.0 - var maxInd = i - - for (k in i until m) { - val absA = kotlin.math.abs(lu[k, i]) - if (absA > maxVal) { - maxVal = absA - maxInd = k - } - } - - //todo check singularity - - if (maxInd != i) { - - val j = pivots[i] - pivots[i] = pivots[maxInd] - pivots[maxInd] = j - - for (k in 0 until m) { - val tmp = lu[i, k] - lu[i, k] = lu[maxInd, k] - lu[maxInd, k] = tmp - } - - pivots[m] += 1 - - } - - for (j in i + 1 until m) { - lu[j, i] /= lu[i, i] - for (k in i + 1 until m) { - lu[j, k] -= lu[j, i] * lu[i, k] - } - } - } - } - override fun DoubleTensor.lu(): Pair { checkSquareMatrix(shape) @@ -80,37 +35,6 @@ public class DoubleLinearOpsTensorAlgebra : } - private inline fun pivInit( - p: MutableStructure2D, - pivot: MutableStructure1D, - n: Int - ) { - for (i in 0 until n) { - p[i, pivot[i]] = 1.0 - } - } - - private inline fun luPivotHelper( - l: MutableStructure2D, - u: MutableStructure2D, - lu: MutableStructure2D, - n: Int - ) { - for (i in 0 until n) { - for (j in 0 until n) { - if (i == j) { - l[i, j] = 1.0 - } - if (j < i) { - l[i, j] = lu[i, j] - } - if (j >= i) { - u[i, j] = lu[i, j] - } - } - } - } - override fun luPivot( luTensor: DoubleTensor, pivotsTensor: IntTensor @@ -139,27 +63,6 @@ public class DoubleLinearOpsTensorAlgebra : } - private inline fun choleskyHelper( - a: MutableStructure2D, - l: MutableStructure2D, - n: Int - ) { - for (i in 0 until n) { - for (j in 0 until i) { - var h = a[i, j] - for (k in 0 until j) { - h -= l[i, k] * l[j, k] - } - l[i, j] = h / l[j, j] - } - var h = a[i, i] - for (j in 0 until i) { - h -= l[i, j] * l[i, j] - } - l[i, i] = sqrt(h) - } - } - override fun DoubleTensor.cholesky(): DoubleTensor { // todo checks checkSquareMatrix(shape) @@ -185,14 +88,6 @@ public class DoubleLinearOpsTensorAlgebra : TODO("ANDREI") } - private fun luMatrixDet(luTensor: MutableStructure2D, pivotsTensor: MutableStructure1D): Double { - val lu = luTensor.as2D() - val pivots = pivotsTensor.as1D() - val m = lu.shape[0] - val sign = if ((pivots[m] - m) % 2 == 0) 1.0 else -1.0 - return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } - } - public fun DoubleTensor.detLU(): DoubleTensor { val (luTensor, pivotsTensor) = lu() val n = shape.size @@ -213,33 +108,6 @@ public class DoubleLinearOpsTensorAlgebra : return detTensor } - private fun luMatrixInv( - lu: MutableStructure2D, - pivots: MutableStructure1D, - invMatrix: MutableStructure2D - ) { - val m = lu.shape[0] - - for (j in 0 until m) { - for (i in 0 until m) { - if (pivots[i] == j) { - invMatrix[i, j] = 1.0 - } - - for (k in 0 until i) { - invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] - } - } - - for (i in m - 1 downTo 0) { - for (k in i + 1 until m) { - invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] - } - invMatrix[i, j] /= lu[i, i] - } - } - } - public fun DoubleTensor.invLU(): DoubleTensor { val (luTensor, pivotsTensor) = lu() val invTensor = luTensor.zeroesLike() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index b418f3647..c878fc58c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,8 +1,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.MutableStructure2D -import space.kscience.kmath.nd.as2D import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra +import space.kscience.kmath.nd.as2D import kotlin.math.abs public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { @@ -230,23 +229,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra, - b: MutableStructure2D, - res: MutableStructure2D, - l: Int, m: Int, n: Int - ) { - for (i in 0 until l) { - for (j in 0 until n) { - var curr = 0.0 - for (k in 0 until m) { - curr += a[i, k] * b[k, j] - } - res[i, j] = curr - } - } - } - override fun DoubleTensor.dot(other: DoubleTensor): DoubleTensor { if (this.shape.size == 1 && other.shape.size == 1) { return DoubleTensor(intArrayOf(1), doubleArrayOf(this.times(other).buffer.array().sum())) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt new file mode 100644 index 000000000..e78cc33c7 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -0,0 +1,188 @@ +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.nd.MutableStructure1D +import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.nd.as1D +import space.kscience.kmath.nd.as2D +import kotlin.math.sqrt + + +internal inline fun BufferedTensor.vectorSequence(): Sequence> = sequence { + val n = shape.size + val vectorOffset = shape[n - 1] + val vectorShape = intArrayOf(shape.last()) + for (offset in 0 until numel step vectorOffset) { + val vector = BufferedTensor(vectorShape, buffer, offset) + yield(vector) + } +} + +internal inline fun BufferedTensor.matrixSequence(): Sequence> = sequence { + check(shape.size >= 2) { "todo" } + val n = shape.size + val matrixOffset = shape[n - 1] * shape[n - 2] + val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) + for (offset in 0 until numel step matrixOffset) { + val matrix = BufferedTensor(matrixShape, buffer, offset) + yield(matrix) + } +} + +internal inline fun BufferedTensor.forEachVector(vectorAction: (BufferedTensor) -> Unit): Unit { + for (vector in vectorSequence()) { + vectorAction(vector) + } +} + +internal inline fun BufferedTensor.forEachMatrix(matrixAction: (BufferedTensor) -> Unit): Unit { + for (matrix in matrixSequence()) { + matrixAction(matrix) + } +} + + +internal inline fun dotHelper( + a: MutableStructure2D, + b: MutableStructure2D, + res: MutableStructure2D, + l: Int, m: Int, n: Int +) { + for (i in 0 until l) { + for (j in 0 until n) { + var curr = 0.0 + for (k in 0 until m) { + curr += a[i, k] * b[k, j] + } + res[i, j] = curr + } + } +} + +internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStructure1D, m: Int) { + for (row in 0 until m) pivots[row] = row + + for (i in 0 until m) { + var maxVal = -1.0 + var maxInd = i + + for (k in i until m) { + val absA = kotlin.math.abs(lu[k, i]) + if (absA > maxVal) { + maxVal = absA + maxInd = k + } + } + + //todo check singularity + + if (maxInd != i) { + + val j = pivots[i] + pivots[i] = pivots[maxInd] + pivots[maxInd] = j + + for (k in 0 until m) { + val tmp = lu[i, k] + lu[i, k] = lu[maxInd, k] + lu[maxInd, k] = tmp + } + + pivots[m] += 1 + + } + + for (j in i + 1 until m) { + lu[j, i] /= lu[i, i] + for (k in i + 1 until m) { + lu[j, k] -= lu[j, i] * lu[i, k] + } + } + } +} + +internal inline fun pivInit( + p: MutableStructure2D, + pivot: MutableStructure1D, + n: Int +) { + for (i in 0 until n) { + p[i, pivot[i]] = 1.0 + } +} + +internal inline fun luPivotHelper( + l: MutableStructure2D, + u: MutableStructure2D, + lu: MutableStructure2D, + n: Int +) { + for (i in 0 until n) { + for (j in 0 until n) { + if (i == j) { + l[i, j] = 1.0 + } + if (j < i) { + l[i, j] = lu[i, j] + } + if (j >= i) { + u[i, j] = lu[i, j] + } + } + } +} + +internal inline fun choleskyHelper( + a: MutableStructure2D, + l: MutableStructure2D, + n: Int +) { + for (i in 0 until n) { + for (j in 0 until i) { + var h = a[i, j] + for (k in 0 until j) { + h -= l[i, k] * l[j, k] + } + l[i, j] = h / l[j, j] + } + var h = a[i, i] + for (j in 0 until i) { + h -= l[i, j] * l[i, j] + } + l[i, i] = sqrt(h) + } +} + +internal inline fun luMatrixDet(luTensor: MutableStructure2D, pivotsTensor: MutableStructure1D): Double { + val lu = luTensor.as2D() + val pivots = pivotsTensor.as1D() + val m = lu.shape[0] + val sign = if ((pivots[m] - m) % 2 == 0) 1.0 else -1.0 + return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } +} + +internal inline fun luMatrixInv( + lu: MutableStructure2D, + pivots: MutableStructure1D, + invMatrix: MutableStructure2D +) { + val m = lu.shape[0] + + for (j in 0 until m) { + for (i in 0 until m) { + if (pivots[i] == j) { + invMatrix[i, j] = 1.0 + } + + for (k in 0 until i) { + invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] + } + } + + for (i in m - 1 downTo 0) { + for (k in i + 1 until m) { + invMatrix[i, j] -= lu[i, k] * invMatrix[k, j] + } + invMatrix[i, j] /= lu[i, i] + } + } +} From 2503d35ba8629055aaffc03f6b2e12e2030d7dd3 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Tue, 30 Mar 2021 14:53:19 +0300 Subject: [PATCH 149/393] complete qr + test qr and lu --- .../core/DoubleLinearOpsTensorAlgebra.kt | 51 +++++++++++++++++-- .../core/TestDoubleLinearOpsAlgebra.kt | 46 +++++++++++++++++ 2 files changed, 92 insertions(+), 5 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 1558e6af9..59ec944f2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -118,7 +118,8 @@ public class DoubleLinearOpsTensorAlgebra : //todo checks checkSquareMatrix(luTensor.shape) check( - luTensor.shape.dropLast(1).toIntArray() contentEquals pivotsTensor.shape + luTensor.shape.dropLast(2).toIntArray() contentEquals pivotsTensor.shape.dropLast(1).toIntArray() || + luTensor.shape.last() == pivotsTensor.shape.last() - 1 ) { "Bed shapes ((" } //todo rewrite val n = luTensor.shape.last() @@ -173,16 +174,56 @@ public class DoubleLinearOpsTensorAlgebra : return lTensor } - private fun matrixQR( - matrix: Structure2D, + private fun MutableStructure1D.dot(other: MutableStructure1D): Double { + var res = 0.0 + for (i in 0 until size) { + res += this[i] * other[i] + } + return res + } + + private fun MutableStructure1D.l2Norm(): Double { + var squareSum = 0.0 + for (i in 0 until size) { + squareSum += this[i] * this[i] + } + return sqrt(squareSum) + } + + fun qrHelper( + matrix: MutableStructure2D, q: MutableStructure2D, r: MutableStructure2D ) { - + //todo check square + val n = matrix.colNum + for (j in 0 until n) { + val v = matrix.columns[j] + if (j > 0) { + for (i in 0 until j) { + r[i, j] = q.columns[i].dot(matrix.columns[j]) + for (k in 0 until n) { + v[k] = v[k] - r[i, j] * q.columns[i][k] + } + } + } + r[j, j] = v.l2Norm() + for (i in 0 until n) { + q[i, j] = v[i] / r[j, j] + } + } } override fun DoubleTensor.qr(): Pair { - TODO("ANDREI") + checkSquareMatrix(shape) + val qTensor = zeroesLike() + val rTensor = zeroesLike() + val seq = matrixSequence().zip((qTensor.matrixSequence().zip(rTensor.matrixSequence()))) + for ((matrix, qr) in seq) { + val (q, r) = qr + qrHelper(matrix.as2D(), q.as2D(), r.as2D()) + } + return Pair(qTensor, rTensor) } override fun DoubleTensor.svd(): Triple { diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index d2d4ffb67..b79c54dd1 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -76,4 +76,50 @@ class TestDoubleLinearOpsTensorAlgebra { val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) assertEquals(a.dot(b).value(), 59.92) } + + @Test + fun testQR() = DoubleLinearOpsTensorAlgebra { + val shape = intArrayOf(2, 2, 2) + val buffer = doubleArrayOf( + 1.0, 3.0, + 1.0, 2.0, + 1.5, 1.0, + 10.0, 2.0 + ) + + val tensor = fromArray(shape, buffer) + + val (q, r) = tensor.qr() + + assertTrue { q.shape contentEquals shape } + assertTrue { r.shape contentEquals shape } + + assertTrue { q.dot(r).buffer.array().epsEqual(buffer) } + + //todo check orthogonality/upper triang. + } + + @Test + fun testLU() = DoubleLinearOpsTensorAlgebra { + val shape = intArrayOf(2, 2, 2) + val buffer = doubleArrayOf( + 1.0, 3.0, + 1.0, 2.0, + 1.5, 1.0, + 10.0, 2.0 + ) + val tensor = fromArray(shape, buffer) + + val (lu, pivots) = tensor.lu() + + // todo check lu + + val (p, l, u) = luPivot(lu, pivots) + + assertTrue { p.shape contentEquals shape } + assertTrue { l.shape contentEquals shape } + assertTrue { u.shape contentEquals shape } + + assertTrue { p.dot(tensor).buffer.array().epsEqual(l.dot(u).buffer.array()) } + } } From 139534fdb343b984c94f5bc089df34b9e1d5946b Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Tue, 30 Mar 2021 15:13:45 +0300 Subject: [PATCH 150/393] fix --- .../kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 59ec944f2..6be50e710 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -183,11 +183,7 @@ public class DoubleLinearOpsTensorAlgebra : } private fun MutableStructure1D.l2Norm(): Double { - var squareSum = 0.0 - for (i in 0 until size) { - squareSum += this[i] * this[i] - } - return sqrt(squareSum) + return sqrt((0 until size).sumOf { this[it] * this[it] }) } fun qrHelper( @@ -223,7 +219,7 @@ public class DoubleLinearOpsTensorAlgebra : val (q, r) = qr qrHelper(matrix.as2D(), q.as2D(), r.as2D()) } - return Pair(qTensor, rTensor) + return qTensor to rTensor } override fun DoubleTensor.svd(): Triple { From 370bab462cae6d883677d0ed5cda7e0b885caa96 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 30 Mar 2021 13:14:09 +0100 Subject: [PATCH 151/393] merged pull request --- .../core/DoubleLinearOpsTensorAlgebra.kt | 40 ------------------- .../kscience/kmath/tensors/core/linutils.kt | 40 +++++++++++++++++++ 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 46ab5f80f..13fb18c01 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -77,46 +77,6 @@ public class DoubleLinearOpsTensorAlgebra : return lTensor } - private fun MutableStructure1D.dot(other: MutableStructure1D): Double { - var res = 0.0 - for (i in 0 until size) { - res += this[i] * other[i] - } - return res - } - - private fun MutableStructure1D.l2Norm(): Double { - var squareSum = 0.0 - for (i in 0 until size) { - squareSum += this[i] * this[i] - } - return sqrt(squareSum) - } - - fun qrHelper( - matrix: MutableStructure2D, - q: MutableStructure2D, - r: MutableStructure2D - ) { - //todo check square - val n = matrix.colNum - for (j in 0 until n) { - val v = matrix.columns[j] - if (j > 0) { - for (i in 0 until j) { - r[i, j] = q.columns[i].dot(matrix.columns[j]) - for (k in 0 until n) { - v[k] = v[k] - r[i, j] * q.columns[i][k] - } - } - } - r[j, j] = v.l2Norm() - for (i in 0 until n) { - q[i, j] = v[i] / r[j, j] - } - } - } - override fun DoubleTensor.qr(): Pair { checkSquareMatrix(shape) val qTensor = zeroesLike() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index e78cc33c7..49a4384c2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -186,3 +186,43 @@ internal inline fun luMatrixInv( } } } + +internal inline fun MutableStructure1D.dot(other: MutableStructure1D): Double { + var res = 0.0 + for (i in 0 until size) { + res += this[i] * other[i] + } + return res +} + +internal inline fun MutableStructure1D.l2Norm(): Double { + var squareSum = 0.0 + for (i in 0 until size) { + squareSum += this[i] * this[i] + } + return sqrt(squareSum) +} + +internal inline fun qrHelper( + matrix: MutableStructure2D, + q: MutableStructure2D, + r: MutableStructure2D +) { + //todo check square + val n = matrix.colNum + for (j in 0 until n) { + val v = matrix.columns[j] + if (j > 0) { + for (i in 0 until j) { + r[i, j] = q.columns[i].dot(matrix.columns[j]) + for (k in 0 until n) { + v[k] = v[k] - r[i, j] * q.columns[i][k] + } + } + } + r[j, j] = v.l2Norm() + for (i in 0 until n) { + q[i, j] = v[i] / r[j, j] + } + } +} From 581c13c573179dd9b2b67e65a4a2c84047ed9171 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 30 Mar 2021 14:14:05 +0100 Subject: [PATCH 152/393] drop code duplication --- kmath-core/api/kmath-core.api | 6 +-- .../core/DoubleLinearOpsTensorAlgebra.kt | 2 +- .../kscience/kmath/tensors/core/linutils.kt | 42 +++++++------------ 3 files changed, 20 insertions(+), 30 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 373920204..634f38bed 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2645,7 +2645,7 @@ public abstract interface class space/kscience/kmath/tensors/LinearOpsTensorAlge public abstract fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun lu (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; public abstract fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; - public abstract fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; + public abstract fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; public abstract fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; public abstract fun symEig (Lspace/kscience/kmath/nd/MutableStructureND;Z)Lkotlin/Pair; } @@ -2794,8 +2794,8 @@ public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebr public fun lu (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Pair; public synthetic fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; public fun luPivot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/IntTensor;)Lkotlin/Triple; - public synthetic fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun qr (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public synthetic fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; + public fun qr (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Pair; public synthetic fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; public fun svd (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Triple; public synthetic fun symEig (Lspace/kscience/kmath/nd/MutableStructureND;Z)Lkotlin/Pair; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 13fb18c01..3d2d21e0c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -84,7 +84,7 @@ public class DoubleLinearOpsTensorAlgebra : val seq = matrixSequence().zip((qTensor.matrixSequence().zip(rTensor.matrixSequence()))) for ((matrix, qr) in seq) { val (q, r) = qr - qrHelper(matrix.as2D(), q.as2D(), r.as2D()) + qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) } return Pair(qTensor, rTensor) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index 49a4384c2..4067de5f4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -187,42 +187,32 @@ internal inline fun luMatrixInv( } } -internal inline fun MutableStructure1D.dot(other: MutableStructure1D): Double { - var res = 0.0 - for (i in 0 until size) { - res += this[i] * other[i] - } - return res -} - -internal inline fun MutableStructure1D.l2Norm(): Double { - var squareSum = 0.0 - for (i in 0 until size) { - squareSum += this[i] * this[i] - } - return sqrt(squareSum) -} - -internal inline fun qrHelper( - matrix: MutableStructure2D, - q: MutableStructure2D, +internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper( + matrix: DoubleTensor, + q: DoubleTensor, r: MutableStructure2D ) { - //todo check square - val n = matrix.colNum + checkSquareMatrix(matrix.shape) + val n = matrix.shape[0] + val qM = q.as2D() + val matrixT = matrix.transpose(0,1) + val qT = q.transpose(0,1) + for (j in 0 until n) { - val v = matrix.columns[j] + val v = matrixT[j] + val vv = v.as1D() if (j > 0) { for (i in 0 until j) { - r[i, j] = q.columns[i].dot(matrix.columns[j]) + r[i, j] = qT[i].dot(matrixT[j]).value() for (k in 0 until n) { - v[k] = v[k] - r[i, j] * q.columns[i][k] + val qTi = qT[i].as1D() + vv[k] = vv[k] - r[i, j] * qTi[k] } } } - r[j, j] = v.l2Norm() + r[j, j] = DoubleAnalyticTensorAlgebra { v.dot(v).sqrt().value() } for (i in 0 until n) { - q[i, j] = v[i] / r[j, j] + qM[i, j] = vv[i] / r[j, j] } } } From 03455a3bebc617e09392e6da7ac361040babf67a Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 30 Mar 2021 14:36:59 +0100 Subject: [PATCH 153/393] infix dot forgotten --- .../space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt | 2 +- .../kotlin/space/kscience/kmath/tensors/core/linutils.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index c878fc58c..965aef1ea 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -229,7 +229,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra 0) { for (i in 0 until j) { - r[i, j] = qT[i].dot(matrixT[j]).value() + r[i, j] = (qT[i] dot matrixT[j]).value() for (k in 0 until n) { val qTi = qT[i].as1D() vv[k] = vv[k] - r[i, j] * qTi[k] } } } - r[j, j] = DoubleAnalyticTensorAlgebra { v.dot(v).sqrt().value() } + r[j, j] = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } From b5d3ca76db28552aa534f04813234047b2b6a9ae Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 30 Mar 2021 19:20:20 +0100 Subject: [PATCH 154/393] Dropping creation methods from interface --- .../kscience/kmath/tensors/TensorAlgebra.kt | 21 ------------------- .../tensors/TensorPartialDivisionAlgebra.kt | 2 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 18 ++++++++-------- .../kscience/kmath/tensors/core/utils.kt | 8 ++++++- 4 files changed, 17 insertions(+), 32 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 5b7515b20..d7c6eaefd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -1,29 +1,10 @@ package space.kscience.kmath.tensors -import space.kscience.kmath.tensors.core.DoubleTensor - // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra> { public fun TensorType.value(): T - //https://pytorch.org/docs/stable/generated/torch.full.html - public fun full(value: T, shape: IntArray): TensorType - - public fun ones(shape: IntArray): TensorType - public fun zeros(shape: IntArray): TensorType - - //https://pytorch.org/docs/stable/generated/torch.full_like.html#torch.full_like - public fun TensorType.fullLike(value: T): TensorType - - public fun TensorType.zeroesLike(): TensorType - public fun TensorType.onesLike(): TensorType - - //https://pytorch.org/docs/stable/generated/torch.eye.html - public fun eye(n: Int): TensorType - - public fun TensorType.copy(): TensorType - public operator fun T.plus(other: TensorType): TensorType public operator fun TensorType.plus(value: T): TensorType public operator fun TensorType.plus(other: TensorType): TensorType @@ -53,8 +34,6 @@ public interface TensorAlgebra> { public fun TensorType.view(shape: IntArray): TensorType public fun TensorType.viewAs(other: TensorType): TensorType - public fun TensorType.eq(other: TensorType, delta: T): Boolean - //https://pytorch.org/docs/stable/generated/torch.matmul.html public infix fun TensorType.dot(other: TensorType): TensorType diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt index 67b9c9d73..0b9079967 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Division_Algebra public interface TensorPartialDivisionAlgebra> : - TensorAlgebra { + TensorAlgebra { public operator fun TensorType.div(value: T): TensorType public operator fun TensorType.div(other: TensorType): TensorType public operator fun TensorType.divAssign(value: T) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 965aef1ea..323ade45d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -27,27 +27,27 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra abs(x - y) < delta } } - override fun DoubleTensor.eq(other: DoubleTensor, delta: Double): Boolean { + public fun DoubleTensor.eq(other: DoubleTensor, delta: Double): Boolean { return this.eq(other) { x, y -> abs(x - y) < delta } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 591ebb89c..33e78db33 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -1,7 +1,8 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.structures.* - +import kotlin.random.Random +import kotlin.math.* /** * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. @@ -34,3 +35,8 @@ internal fun Buffer.array(): DoubleArray = when (this) { is DoubleBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") } + +internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { + val u = Random(seed) + return (0 until n).map { sqrt(-2.0 * u.nextDouble()) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() +} From 07b6f988c296592cc28c93de12009fced255f43d Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 30 Mar 2021 19:31:42 +0100 Subject: [PATCH 155/393] forgot ln --- .../kotlin/space/kscience/kmath/tensors/core/utils.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 33e78db33..d8a073d64 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -38,5 +38,5 @@ internal fun Buffer.array(): DoubleArray = when (this) { internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { val u = Random(seed) - return (0 until n).map { sqrt(-2.0 * u.nextDouble()) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() + return (0 until n).map { sqrt(-2.0 * ln(u.nextDouble())) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() } From 9574099f9bb7062d5fe364189f7521f760ccad8c Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 31 Mar 2021 02:24:21 +0700 Subject: [PATCH 156/393] Fix post-merge issues --- examples/build.gradle.kts | 1 + .../kmath/commons/fit/fitWithAutoDiff.kt | 34 ++-- .../kmath/stat/DistributionBenchmark.kt | 4 +- .../kscience/kmath/stat/DistributionDemo.kt | 8 +- .../commons/optimization/OptimizeTest.kt | 29 ++-- .../space/kscience/kmath/structures/Buffer.kt | 157 +++++++++--------- .../kmath/chains/BlockingRealChain.kt | 9 - .../kmath/chains/BlockingDoubleChain.kt | 13 +- .../kscience/dimensions/DMatrixContextTest.kt | 2 +- .../kscience/kmath/stat/SamplerAlgebra.kt | 34 ---- .../space/kscience/kmath/stat/Distribution.kt | 19 ++- .../space/kscience/kmath/stat/RandomChain.kt | 10 +- .../kscience/kmath/stat/SamplerAlgebra.kt | 28 +++- .../stat/distributions/NormalDistribution.kt | 16 +- .../kmath/stat/internal/InternalErf.kt | 2 +- .../kmath/stat/internal/InternalGamma.kt | 2 +- .../kmath/stat/internal/InternalUtils.kt | 2 +- .../AhrensDieterExponentialSampler.kt | 12 +- .../AhrensDieterMarsagliaTsangGammaSampler.kt | 12 +- .../samplers/AliasMethodDiscreteSampler.kt | 12 +- .../BoxMullerNormalizedGaussianSampler.kt | 10 +- .../kmath/stat/samplers/GaussianSampler.kt | 10 +- .../samplers/KempSmallMeanPoissonSampler.kt | 10 +- .../stat/samplers/LargeMeanPoissonSampler.kt | 16 +- .../MarsagliaNormalizedGaussianSampler.kt | 10 +- .../samplers/NormalizedGaussianSampler.kt | 4 +- .../kmath/stat/samplers/PoissonSampler.kt | 8 +- .../stat/samplers/SmallMeanPoissonSampler.kt | 10 +- .../ZigguratNormalizedGaussianSampler.kt | 10 +- .../kmath/stat/CommonsDistributionsTest.kt | 2 +- 30 files changed, 234 insertions(+), 262 deletions(-) delete mode 100644 kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingRealChain.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/SamplerAlgebra.kt rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/distributions/NormalDistribution.kt (72%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/internal/InternalErf.kt (90%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/internal/InternalGamma.kt (99%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/internal/InternalUtils.kt (98%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt (88%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt (94%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt (97%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt (88%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/samplers/GaussianSampler.kt (86%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt (92%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt (92%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt (91%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt (72%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/samplers/PoissonSampler.kt (88%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt (88%) rename kmath-stat/src/commonMain/kotlin/{ => space}/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt (93%) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 5dd40b609..a48b4d0d9 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -106,6 +106,7 @@ kotlin.sourceSets.all { with(languageSettings) { useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes") + useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") } } diff --git a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt index 22d642d92..04c55b34c 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -1,20 +1,22 @@ -package kscience.kmath.commons.fit +package space.kscience.kmath.commons.fit import kotlinx.html.br import kotlinx.html.h3 -import kscience.kmath.commons.optimization.chiSquared -import kscience.kmath.commons.optimization.minimize -import kscience.kmath.expressions.symbol -import kscience.kmath.real.RealVector -import kscience.kmath.real.map -import kscience.kmath.real.step -import kscience.kmath.stat.* -import kscience.kmath.stat.distributions.NormalDistribution -import kscience.kmath.structures.asIterable -import kscience.kmath.structures.toList import kscience.plotly.* import kscience.plotly.models.ScatterMode import kscience.plotly.models.TraceValues +import space.kscience.kmath.commons.optimization.chiSquared +import space.kscience.kmath.commons.optimization.minimize +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.optimization.FunctionOptimization +import space.kscience.kmath.optimization.OptimizationResult +import space.kscience.kmath.real.DoubleVector +import space.kscience.kmath.real.map +import space.kscience.kmath.real.step +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.distributions.NormalDistribution +import space.kscience.kmath.structures.asIterable +import space.kscience.kmath.structures.toList import kotlin.math.pow import kotlin.math.sqrt @@ -27,7 +29,7 @@ private val c by symbol /** * Shortcut to use buffers in plotly */ -operator fun TraceValues.invoke(vector: RealVector) { +operator fun TraceValues.invoke(vector: DoubleVector) { numbers = vector.asIterable() } @@ -58,12 +60,12 @@ suspend fun main() { val yErr = y.map { sqrt(it) }//RealVector.same(x.size, sigma) // compute differentiable chi^2 sum for given model ax^2 + bx + c - val chi2 = Fitting.chiSquared(x, y, yErr) { x1 -> + val chi2 = FunctionOptimization.chiSquared(x, y, yErr) { x1 -> //bind variables to autodiff context val a = bind(a) val b = bind(b) //Include default value for c if it is not provided as a parameter - val c = bindOrNull(c) ?: one + val c = bindSymbolOrNull(c) ?: one a * x1.pow(2) + b * x1 + c } @@ -90,10 +92,10 @@ suspend fun main() { } } br() - h3{ + h3 { +"Fit result: $result" } - h3{ + h3 { +"Chi2/dof = ${result.value / (x.size - 3)}" } } diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt index 4478903d9..bfd138502 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt @@ -1,9 +1,9 @@ -package kscience.kmath.stat +package space.kscience.kmath.stat import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking -import kscience.kmath.stat.samplers.GaussianSampler +import space.kscience.kmath.stat.samplers.GaussianSampler import org.apache.commons.rng.simple.RandomSource import java.time.Duration import java.time.Instant diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt index dd04c12e5..aac7d51d4 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt @@ -1,9 +1,9 @@ -package kscience.kmath.stat +package space.kscience.kmath.stat import kotlinx.coroutines.runBlocking -import kscience.kmath.chains.Chain -import kscience.kmath.chains.collectWithState -import kscience.kmath.stat.distributions.NormalDistribution +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.chains.collectWithState +import space.kscience.kmath.stat.distributions.NormalDistribution /** * The state of distribution averager. diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt index 184d209d5..36f2639f4 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -1,13 +1,13 @@ -package kscience.kmath.commons.optimization +package space.kscience.kmath.commons.optimization import kotlinx.coroutines.runBlocking -import kscience.kmath.commons.expressions.DerivativeStructureExpression -import kscience.kmath.expressions.symbol -import kscience.kmath.stat.Fitting -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.distributions.NormalDistribution -import org.junit.jupiter.api.Test +import space.kscience.kmath.commons.expressions.DerivativeStructureExpression +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.optimization.FunctionOptimization +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.distributions.NormalDistribution import kotlin.math.pow +import kotlin.test.Test internal class OptimizeTest { val x by symbol @@ -34,6 +34,7 @@ internal class OptimizeTest { simplexSteps(x to 2.0, y to 0.5) //this sets simplex optimizer } + println(result.point) println(result.value) } @@ -43,15 +44,20 @@ internal class OptimizeTest { val a by symbol val b by symbol val c by symbol + val sigma = 1.0 val generator = NormalDistribution(0.0, sigma) val chain = generator.sample(RandomGenerator.default(112667)) val x = (1..100).map(Int::toDouble) - val y = x.map { it.pow(2) + it + 1.0 + chain.next() } + + val y = x.map { + it.pow(2) + it + 1 + chain.next() + } + val yErr = List(x.size) { sigma } - val chi2 = Fitting.chiSquared(x, y, yErr) { x1 -> - val cWithDefault = bindOrNull(c) ?: one + val chi2 = FunctionOptimization.chiSquared(x, y, yErr) { x1 -> + val cWithDefault = bindSymbolOrNull(c) ?: one bind(a) * x1.pow(2) + bind(b) * x1 + cWithDefault } @@ -59,5 +65,4 @@ internal class OptimizeTest { println(result) println("Chi2/dof = ${result.value / (x.size - 3)}") } - -} \ No newline at end of file +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index c5a51ca50..168a92c37 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -1,4 +1,4 @@ -package kscience.kmath.structures +package space.kscience.kmath.structures import kotlin.reflect.KClass @@ -17,11 +17,13 @@ public typealias BufferFactory = (Int, (Int) -> T) -> Buffer public typealias MutableBufferFactory = (Int, (Int) -> T) -> MutableBuffer /** - * A generic immutable random-access structure for both primitives and objects. + * A generic read-only random-access structure for both primitives and objects. + * + * [Buffer] is in general identity-free. [Buffer.contentEquals] should be used for content equality checks. * * @param T the type of elements contained in the buffer. */ -public interface Buffer { +public interface Buffer { /** * The size of this buffer. */ @@ -37,49 +39,45 @@ public interface Buffer { */ public operator fun iterator(): Iterator - /** - * Checks content equality with another buffer. - */ - public fun contentEquals(other: Buffer<*>): Boolean = - asSequence().mapIndexed { index, value -> value == other[index] }.all { it } - public companion object { /** - * Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified - * [initializer] function. + * Check the element-by-element match of content of two buffers. */ - public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer = - RealBuffer(size) { initializer(it) } + public fun contentEquals(first: Buffer, second: Buffer): Boolean{ + if (first.size != second.size) return false + for (i in first.indices) { + if (first[i] != second[i]) return false + } + return true + } /** * Creates a [ListBuffer] of given type [T] with given [size]. Each element is calculated by calling the * specified [initializer] function. */ public inline fun boxing(size: Int, initializer: (Int) -> T): Buffer = - ListBuffer(List(size, initializer)) - - // TODO add resolution based on Annotation or companion resolution + List(size, initializer).asBuffer() /** * Creates a [Buffer] of given [type]. If the type is primitive, specialized buffers are used ([IntBuffer], - * [RealBuffer], etc.), [ListBuffer] is returned otherwise. + * [DoubleBuffer], etc.), [ListBuffer] is returned otherwise. * * The [size] is specified, and each element is calculated by calling the specified [initializer] function. */ @Suppress("UNCHECKED_CAST") public inline fun auto(type: KClass, size: Int, initializer: (Int) -> T): Buffer = when (type) { - Double::class -> real(size) { initializer(it) as Double } as Buffer - Short::class -> ShortBuffer(size) { initializer(it) as Short } as Buffer - Int::class -> IntBuffer(size) { initializer(it) as Int } as Buffer - Long::class -> LongBuffer(size) { initializer(it) as Long } as Buffer - Float::class -> FloatBuffer(size) { initializer(it) as Float } as Buffer + Double::class -> MutableBuffer.double(size) { initializer(it) as Double } as Buffer + Short::class -> MutableBuffer.short(size) { initializer(it) as Short } as Buffer + Int::class -> MutableBuffer.int(size) { initializer(it) as Int } as Buffer + Long::class -> MutableBuffer.long(size) { initializer(it) as Long } as Buffer + Float::class -> MutableBuffer.float(size) { initializer(it) as Float } as Buffer else -> boxing(size, initializer) } /** * Creates a [Buffer] of given type [T]. If the type is primitive, specialized buffers are used ([IntBuffer], - * [RealBuffer], etc.), [ListBuffer] is returned otherwise. + * [DoubleBuffer], etc.), [ListBuffer] is returned otherwise. * * The [size] is specified, and each element is calculated by calling the specified [initializer] function. */ @@ -89,21 +87,6 @@ public interface Buffer { } } -/** - * Creates a sequence that returns all elements from this [Buffer]. - */ -public fun Buffer.asSequence(): Sequence = Sequence(::iterator) - -/** - * Creates an iterable that returns all elements from this [Buffer]. - */ -public fun Buffer.asIterable(): Iterable = Iterable(::iterator) - -/** - * Converts this [Buffer] to a new [List] - */ -public fun Buffer.toList(): List = asSequence().toList() - /** * Returns an [IntRange] of the valid indices for this [Buffer]. */ @@ -126,6 +109,43 @@ public interface MutableBuffer : Buffer { public fun copy(): MutableBuffer public companion object { + /** + * Creates a [DoubleBuffer] with the specified [size], where each element is calculated by calling the specified + * [initializer] function. + */ + public inline fun double(size: Int, initializer: (Int) -> Double): DoubleBuffer = + DoubleBuffer(size, initializer) + + /** + * Creates a [ShortBuffer] with the specified [size], where each element is calculated by calling the specified + * [initializer] function. + */ + public inline fun short(size: Int, initializer: (Int) -> Short): ShortBuffer = + ShortBuffer(size, initializer) + + /** + * Creates a [IntBuffer] with the specified [size], where each element is calculated by calling the specified + * [initializer] function. + */ + public inline fun int(size: Int, initializer: (Int) -> Int): IntBuffer = + IntBuffer(size, initializer) + + /** + * Creates a [LongBuffer] with the specified [size], where each element is calculated by calling the specified + * [initializer] function. + */ + public inline fun long(size: Int, initializer: (Int) -> Long): LongBuffer = + LongBuffer(size, initializer) + + + /** + * Creates a [FloatBuffer] with the specified [size], where each element is calculated by calling the specified + * [initializer] function. + */ + public inline fun float(size: Int, initializer: (Int) -> Float): FloatBuffer = + FloatBuffer(size, initializer) + + /** * Create a boxing mutable buffer of given type */ @@ -134,37 +154,30 @@ public interface MutableBuffer : Buffer { /** * Creates a [MutableBuffer] of given [type]. If the type is primitive, specialized buffers are used - * ([IntBuffer], [RealBuffer], etc.), [ListBuffer] is returned otherwise. + * ([IntBuffer], [DoubleBuffer], etc.), [ListBuffer] is returned otherwise. * * The [size] is specified, and each element is calculated by calling the specified [initializer] function. */ @Suppress("UNCHECKED_CAST") public inline fun auto(type: KClass, size: Int, initializer: (Int) -> T): MutableBuffer = when (type) { - Double::class -> RealBuffer(size) { initializer(it) as Double } as MutableBuffer - Short::class -> ShortBuffer(size) { initializer(it) as Short } as MutableBuffer - Int::class -> IntBuffer(size) { initializer(it) as Int } as MutableBuffer - Float::class -> FloatBuffer(size) { initializer(it) as Float } as MutableBuffer - Long::class -> LongBuffer(size) { initializer(it) as Long } as MutableBuffer + Double::class -> double(size) { initializer(it) as Double } as MutableBuffer + Short::class -> short(size) { initializer(it) as Short } as MutableBuffer + Int::class -> int(size) { initializer(it) as Int } as MutableBuffer + Float::class -> float(size) { initializer(it) as Float } as MutableBuffer + Long::class -> long(size) { initializer(it) as Long } as MutableBuffer else -> boxing(size, initializer) } /** * Creates a [MutableBuffer] of given type [T]. If the type is primitive, specialized buffers are used - * ([IntBuffer], [RealBuffer], etc.), [ListBuffer] is returned otherwise. + * ([IntBuffer], [DoubleBuffer], etc.), [ListBuffer] is returned otherwise. * * The [size] is specified, and each element is calculated by calling the specified [initializer] function. */ @Suppress("UNCHECKED_CAST") public inline fun auto(size: Int, initializer: (Int) -> T): MutableBuffer = auto(T::class, size, initializer) - - /** - * Creates a [RealBuffer] with the specified [size], where each element is calculated by calling the specified - * [initializer] function. - */ - public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer = - RealBuffer(size) { initializer(it) } } } @@ -187,15 +200,6 @@ public inline class ListBuffer(public val list: List) : Buffer { */ public fun List.asBuffer(): ListBuffer = ListBuffer(this) -/** - * Creates a new [ListBuffer] with the specified [size], where each element is calculated by calling the specified - * [init] function. - * - * The function [init] is called for each array element sequentially starting from the first one. - * It should return the value for an array element given its index. - */ -public inline fun ListBuffer(size: Int, init: (Int) -> T): ListBuffer = List(size, init).asBuffer() - /** * [MutableBuffer] implementation over [MutableList]. * @@ -216,16 +220,20 @@ public inline class MutableListBuffer(public val list: MutableList) : Muta override fun copy(): MutableBuffer = MutableListBuffer(ArrayList(list)) } +/** + * Returns an [ListBuffer] that wraps the original list. + */ +public fun MutableList.asMutableBuffer(): MutableListBuffer = MutableListBuffer(this) + /** * [MutableBuffer] implementation over [Array]. * * @param T the type of elements contained in the buffer. * @property array The underlying array. */ -public class ArrayBuffer(private val array: Array) : MutableBuffer { +public class ArrayBuffer(internal val array: Array) : MutableBuffer { // Can't inline because array is invariant - override val size: Int - get() = array.size + override val size: Int get() = array.size override operator fun get(index: Int): T = array[index] @@ -237,6 +245,7 @@ public class ArrayBuffer(private val array: Array) : MutableBuffer { override fun copy(): MutableBuffer = ArrayBuffer(array.copyOf()) } + /** * Returns an [ArrayBuffer] that wraps the original array. */ @@ -269,27 +278,9 @@ public class VirtualBuffer(override val size: Int, private val generator: (In } override operator fun iterator(): Iterator = (0 until size).asSequence().map(generator).iterator() - - override fun contentEquals(other: Buffer<*>): Boolean { - return if (other is VirtualBuffer) { - this.size == other.size && this.generator == other.generator - } else { - super.contentEquals(other) - } - } } /** * Convert this buffer to read-only buffer. */ -public fun Buffer.asReadOnly(): Buffer = if (this is MutableBuffer) ReadOnlyBuffer(this) else this - -/** - * Typealias for buffer transformations. - */ -public typealias BufferTransform = (Buffer) -> Buffer - -/** - * Typealias for buffer transformations with suspend function. - */ -public typealias SuspendBufferTransform = suspend (Buffer) -> Buffer +public fun Buffer.asReadOnly(): Buffer = if (this is MutableBuffer) ReadOnlyBuffer(this) else this \ No newline at end of file diff --git a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingRealChain.kt b/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingRealChain.kt deleted file mode 100644 index 7c463b109..000000000 --- a/kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingRealChain.kt +++ /dev/null @@ -1,9 +0,0 @@ -package kscience.kmath.chains - -/** - * Performance optimized chain for real values - */ -public interface BlockingRealChain : Chain { - public override suspend fun next(): Double - public suspend fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { next() } -} diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt index ba6adf35b..d024147b4 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt @@ -1,12 +1,13 @@ package space.kscience.kmath.chains /** - * Performance optimized chain for real values + * Chunked, specialized chain for real values. */ -public abstract class BlockingDoubleChain : Chain { - public abstract fun nextDouble(): Double +public interface BlockingDoubleChain : Chain { + public override suspend fun next(): Double - override suspend fun next(): Double = nextDouble() - - public open fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { nextDouble() } + /** + * Returns an [DoubleArray] chunk of [size] values of [next]. + */ + public suspend fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { next() } } diff --git a/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt b/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt index e2a9628ac..58ed82723 100644 --- a/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt +++ b/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt @@ -1,4 +1,4 @@ -package kscience.dimensions +package space.kscience.dimensions import space.kscience.kmath.dimensions.D2 import space.kscience.kmath.dimensions.D3 diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/SamplerAlgebra.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/SamplerAlgebra.kt deleted file mode 100644 index 8413424de..000000000 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/SamplerAlgebra.kt +++ /dev/null @@ -1,34 +0,0 @@ -package kscience.kmath.stat - -import kscience.kmath.chains.Chain -import kscience.kmath.chains.ConstantChain -import kscience.kmath.chains.map -import kscience.kmath.chains.zip -import kscience.kmath.operations.Space -import kscience.kmath.operations.invoke - -/** - * Implements [Sampler] by sampling only certain [value]. - * - * @property value the value to sample. - */ -public class ConstantSampler(public val value: T) : Sampler { - public override fun sample(generator: RandomGenerator): Chain = ConstantChain(value) -} - -/** - * A space of samplers. Allows to perform simple operations on distributions. - * - * @property space the space to provide addition and scalar multiplication for [T]. - */ -public class SamplerSpace(public val space: Space) : Space> { - public override val zero: Sampler = ConstantSampler(space.zero) - - public override fun add(a: Sampler, b: Sampler): Sampler = Sampler { generator -> - a.sample(generator).zip(b.sample(generator)) { aValue, bValue -> space { aValue + bValue } } - } - - public override fun multiply(a: Sampler, k: Number): Sampler = Sampler { generator -> - a.sample(generator).map { space { it * k.toDouble() } } - } -} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt index f85ba5d68..095182160 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt @@ -1,11 +1,12 @@ -package kscience.kmath.stat +package space.kscience.kmath.stat import kotlinx.coroutines.flow.first -import kscience.kmath.chains.Chain -import kscience.kmath.chains.collect -import kscience.kmath.structures.Buffer -import kscience.kmath.structures.BufferFactory -import kscience.kmath.structures.IntBuffer +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.chains.collect +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferFactory +import space.kscience.kmath.structures.IntBuffer +import space.kscience.kmath.structures.MutableBuffer import kotlin.jvm.JvmName /** @@ -22,7 +23,7 @@ public fun interface Sampler { } /** - * A distribution of typed objects + * A distribution of typed objects. */ public interface Distribution : Sampler { /** @@ -60,7 +61,7 @@ public fun > UnivariateDistribution.integral(from: T, to: T public fun Sampler.sampleBuffer( generator: RandomGenerator, size: Int, - bufferFactory: BufferFactory = Buffer.Companion::boxing + bufferFactory: BufferFactory = Buffer.Companion::boxing, ): Chain> { require(size > 1) //creating temporary storage once @@ -86,7 +87,7 @@ public suspend fun Sampler.next(generator: RandomGenerator): T = sa */ @JvmName("sampleRealBuffer") public fun Sampler.sampleBuffer(generator: RandomGenerator, size: Int): Chain> = - sampleBuffer(generator, size, Buffer.Companion::real) + sampleBuffer(generator, size, MutableBuffer.Companion::double) /** * Generates [size] integer samples and chunks them into some buffers. diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt index daad7392a..2f117a035 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt @@ -1,8 +1,8 @@ -package kscience.kmath.stat +package space.kscience.kmath.stat -import kscience.kmath.chains.BlockingIntChain -import kscience.kmath.chains.BlockingRealChain -import kscience.kmath.chains.Chain +import space.kscience.kmath.chains.BlockingDoubleChain +import space.kscience.kmath.chains.BlockingIntChain +import space.kscience.kmath.chains.Chain /** * A possibly stateful chain producing random values. @@ -18,5 +18,5 @@ public class RandomChain( } public fun RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain = RandomChain(this, gen) -public fun Chain.blocking(): BlockingRealChain = object : Chain by this, BlockingRealChain {} +public fun Chain.blocking(): BlockingDoubleChain = object : Chain by this, BlockingDoubleChain {} public fun Chain.blocking(): BlockingIntChain = object : Chain by this, BlockingIntChain {} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt index c5ec99dae..25ec7eca6 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt @@ -8,16 +8,28 @@ import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke -public class BasicSampler(public val chainBuilder: (RandomGenerator) -> Chain) : Sampler { - public override fun sample(generator: RandomGenerator): Chain = chainBuilder(generator) -} - +/** + * Implements [Sampler] by sampling only certain [value]. + * + * @property value the value to sample. + */ public class ConstantSampler(public val value: T) : Sampler { public override fun sample(generator: RandomGenerator): Chain = ConstantChain(value) } /** - * A space for samplers. Allows to perform simple operations on distributions + * Implements [Sampler] by delegating sampling to value of [chainBuilder]. + * + * @property chainBuilder the provider of [Chain]. + */ +public class BasicSampler(public val chainBuilder: (RandomGenerator) -> Chain) : Sampler { + public override fun sample(generator: RandomGenerator): Chain = chainBuilder(generator) +} + +/** + * A space of samplers. Allows to perform simple operations on distributions. + * + * @property algebra the space to provide addition and scalar multiplication for [T]. */ public class SamplerSpace(public val algebra: S) : Group>, ScaleOperations> where S : Group, S : ScaleOperations { @@ -29,8 +41,10 @@ public class SamplerSpace(public val algebra: S) : Group> } public override fun scale(a: Sampler, value: Double): Sampler = BasicSampler { generator -> - a.sample(generator).map { algebra { it * value } } + a.sample(generator).map { a -> + algebra { a * value } + } } - override fun Sampler.unaryMinus(): Sampler = scale(this, -1.0) + public override fun Sampler.unaryMinus(): Sampler = scale(this, -1.0) } diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/distributions/NormalDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/distributions/NormalDistribution.kt similarity index 72% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/distributions/NormalDistribution.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/distributions/NormalDistribution.kt index 9059a0038..6515cbaa7 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/distributions/NormalDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/distributions/NormalDistribution.kt @@ -1,12 +1,12 @@ -package kscience.kmath.stat.distributions +package space.kscience.kmath.stat.distributions -import kscience.kmath.chains.Chain -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.UnivariateDistribution -import kscience.kmath.stat.internal.InternalErf -import kscience.kmath.stat.samplers.GaussianSampler -import kscience.kmath.stat.samplers.NormalizedGaussianSampler -import kscience.kmath.stat.samplers.ZigguratNormalizedGaussianSampler +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.UnivariateDistribution +import space.kscience.kmath.stat.internal.InternalErf +import space.kscience.kmath.stat.samplers.GaussianSampler +import space.kscience.kmath.stat.samplers.NormalizedGaussianSampler +import space.kscience.kmath.stat.samplers.ZigguratNormalizedGaussianSampler import kotlin.math.* /** diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalErf.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalErf.kt similarity index 90% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalErf.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalErf.kt index 04eb3ef0e..4e1623867 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalErf.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalErf.kt @@ -1,4 +1,4 @@ -package kscience.kmath.stat.internal +package space.kscience.kmath.stat.internal import kotlin.math.abs diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalGamma.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalGamma.kt similarity index 99% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalGamma.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalGamma.kt index dce84712a..4f5adbe97 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalGamma.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalGamma.kt @@ -1,4 +1,4 @@ -package kscience.kmath.stat.internal +package space.kscience.kmath.stat.internal import kotlin.math.* diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalUtils.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalUtils.kt similarity index 98% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalUtils.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalUtils.kt index 9997eeb57..722eee946 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/internal/InternalUtils.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalUtils.kt @@ -1,4 +1,4 @@ -package kscience.kmath.stat.internal +package space.kscience.kmath.stat.internal import kotlin.math.ln import kotlin.math.min diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt similarity index 88% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt index 853e952bb..504c6b881 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt @@ -1,10 +1,10 @@ -package kscience.kmath.stat.samplers +package space.kscience.kmath.stat.samplers -import kscience.kmath.chains.Chain -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.Sampler -import kscience.kmath.stat.chain -import kscience.kmath.stat.internal.InternalUtils +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.stat.chain +import space.kscience.kmath.stat.internal.InternalUtils import kotlin.math.ln import kotlin.math.pow diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt similarity index 94% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt index 98cb83332..81182f6cd 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt @@ -1,10 +1,10 @@ -package kscience.kmath.stat.samplers +package space.kscience.kmath.stat.samplers -import kscience.kmath.chains.Chain -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.Sampler -import kscience.kmath.stat.chain -import kscience.kmath.stat.next +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.stat.chain +import space.kscience.kmath.stat.next import kotlin.math.* /** diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt similarity index 97% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt index a4dc537b5..cae97db65 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt @@ -1,10 +1,10 @@ -package kscience.kmath.stat.samplers +package space.kscience.kmath.stat.samplers -import kscience.kmath.chains.Chain -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.Sampler -import kscience.kmath.stat.chain -import kscience.kmath.stat.internal.InternalUtils +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.stat.chain +import space.kscience.kmath.stat.internal.InternalUtils import kotlin.math.ceil import kotlin.math.max import kotlin.math.min diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt similarity index 88% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt index 20412f64b..04beb448d 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt @@ -1,9 +1,9 @@ -package kscience.kmath.stat.samplers +package space.kscience.kmath.stat.samplers -import kscience.kmath.chains.Chain -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.Sampler -import kscience.kmath.stat.chain +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.stat.chain import kotlin.math.* /** diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/GaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/GaussianSampler.kt similarity index 86% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/GaussianSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/GaussianSampler.kt index 92dd27d02..eba26cfb5 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/GaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/GaussianSampler.kt @@ -1,9 +1,9 @@ -package kscience.kmath.stat.samplers +package space.kscience.kmath.stat.samplers -import kscience.kmath.chains.Chain -import kscience.kmath.chains.map -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.Sampler +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.chains.map +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler /** * Sampling from a Gaussian distribution with given mean and standard deviation. diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt similarity index 92% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt index 78da230ca..1d7f90023 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt @@ -1,9 +1,9 @@ -package kscience.kmath.stat.samplers +package space.kscience.kmath.stat.samplers -import kscience.kmath.chains.Chain -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.Sampler -import kscience.kmath.stat.chain +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.stat.chain import kotlin.math.exp /** diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt similarity index 92% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt index c880d7a20..de1e7cc89 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt @@ -1,12 +1,12 @@ -package kscience.kmath.stat.samplers +package space.kscience.kmath.stat.samplers -import kscience.kmath.chains.Chain -import kscience.kmath.chains.ConstantChain -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.Sampler -import kscience.kmath.stat.chain -import kscience.kmath.stat.internal.InternalUtils -import kscience.kmath.stat.next +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.chains.ConstantChain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.stat.chain +import space.kscience.kmath.stat.internal.InternalUtils +import space.kscience.kmath.stat.next import kotlin.math.* /** diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt similarity index 91% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt index 8077f9f75..8a659642f 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt @@ -1,9 +1,9 @@ -package kscience.kmath.stat.samplers +package space.kscience.kmath.stat.samplers -import kscience.kmath.chains.Chain -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.Sampler -import kscience.kmath.stat.chain +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.stat.chain import kotlin.math.ln import kotlin.math.sqrt diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt similarity index 72% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt index 8995d3030..4eb3d60e0 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt @@ -1,6 +1,6 @@ -package kscience.kmath.stat.samplers +package space.kscience.kmath.stat.samplers -import kscience.kmath.stat.Sampler +import space.kscience.kmath.stat.Sampler /** * Marker interface for a sampler that generates values from an N(0,1) diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/PoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/PoissonSampler.kt similarity index 88% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/PoissonSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/PoissonSampler.kt index e9a6244a6..0c0234892 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/PoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/PoissonSampler.kt @@ -1,8 +1,8 @@ -package kscience.kmath.stat.samplers +package space.kscience.kmath.stat.samplers -import kscience.kmath.chains.Chain -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.Sampler +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler /** * Sampler for the Poisson distribution. diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt similarity index 88% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt index e9ce8a6a6..0fe7ff161 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt @@ -1,9 +1,9 @@ -package kscience.kmath.stat.samplers +package space.kscience.kmath.stat.samplers -import kscience.kmath.chains.Chain -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.Sampler -import kscience.kmath.stat.chain +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.stat.chain import kotlin.math.ceil import kotlin.math.exp diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt similarity index 93% rename from kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt index e9e8d91da..90815209f 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt @@ -1,9 +1,9 @@ -package kscience.kmath.stat.samplers +package space.kscience.kmath.stat.samplers -import kscience.kmath.chains.Chain -import kscience.kmath.stat.RandomGenerator -import kscience.kmath.stat.Sampler -import kscience.kmath.stat.chain +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.stat.chain import kotlin.math.* /** diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt index 59320e6b5..76aac65c4 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -3,9 +3,9 @@ package space.kscience.kmath.stat import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.toList import kotlinx.coroutines.runBlocking -import kscience.kmath.stat.samplers.GaussianSampler import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test +import space.kscience.kmath.stat.samplers.GaussianSampler internal class CommonsDistributionsTest { @Test From 6305acea68a8b34e9ddd01b7daf1711f17829151 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 31 Mar 2021 08:32:53 +0100 Subject: [PATCH 157/393] API dump --- kmath-core/api/kmath-core.api | 36 +++++++++-------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 634f38bed..f0e749d2b 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2655,21 +2655,14 @@ public final class space/kscience/kmath/tensors/LinearOpsTensorAlgebra$DefaultIm } public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { - public abstract fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun eq (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Z - public abstract fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun fullLike (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V public abstract fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun ones ([I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun onesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2685,8 +2678,6 @@ public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { public abstract fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; public abstract fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; public abstract fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun zeroesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun zeros ([I)Lspace/kscience/kmath/nd/MutableStructureND; } public final class space/kscience/kmath/tensors/TensorAlgebra$DefaultImpls { @@ -2814,8 +2805,7 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z public static synthetic fun contentEquals$default (Lspace/kscience/kmath/tensors/core/DoubleTensorAlgebra;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;DILjava/lang/Object;)Z - public synthetic fun copy (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun copy (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun copy (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; public fun diagonalEmbedding (Lspace/kscience/kmath/tensors/core/DoubleTensor;III)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2828,16 +2818,12 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V public synthetic fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun dot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun eq (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Z public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Z - public fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z - public synthetic fun eye (I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z + public final fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public final fun fromArray ([I[D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun full (D[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun full (Ljava/lang/Object;[I)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun fullLike (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun fullLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun full (D[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun fullLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; public fun get (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public final fun map (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/tensors/core/DoubleTensor; @@ -2851,10 +2837,8 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun ones ([I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun ones ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun onesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun onesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun ones ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun onesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public fun plus (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; @@ -2885,10 +2869,8 @@ public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscie public fun view (Lspace/kscience/kmath/tensors/core/DoubleTensor;[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; public synthetic fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; public fun viewAs (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun zeroesLike (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun zeroesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun zeros ([I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun zeros ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun zeroesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; + public final fun zeros ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; } public final class space/kscience/kmath/tensors/core/DoubleTensorAlgebraKt { From 5abd63cde28fcf63e72809799b10211647adb73b Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 31 Mar 2021 09:07:45 +0100 Subject: [PATCH 158/393] moving to kmath-tensors module --- kmath-core/api/kmath-core.api | 278 ------------------ kmath-tensors/build.gradle.kts | 16 + .../kmath/tensors/AnalyticTensorAlgebra.kt | 0 .../kmath/tensors/LinearOpsTensorAlgebra.kt | 0 .../kscience/kmath/tensors/TensorAlgebra.kt | 0 .../tensors/TensorPartialDivisionAlgebra.kt | 0 .../kscience/kmath/tensors/TensorStructure.kt | 0 .../core/BroadcastDoubleTensorAlgebra.kt | 0 .../kmath/tensors/core/BufferedTensor.kt | 0 .../core/DoubleAnalyticTensorAlgebra.kt | 0 .../core/DoubleLinearOpsTensorAlgebra.kt | 0 .../kmath/tensors/core/DoubleTensorAlgebra.kt | 0 .../tensors/core/TensorLinearStructure.kt | 0 .../kscience/kmath/tensors/core/checks.kt | 0 .../kscience/kmath/tensors/core/linutils.kt | 0 .../kscience/kmath/tensors/core/utils.kt | 0 .../kmath/tensors/core/TestBroadcasting.kt | 0 .../core/TestDoubleAnalyticTensorAlgebra.kt | 0 .../core/TestDoubleLinearOpsAlgebra.kt | 0 .../kmath/tensors/core/TestDoubleTensor.kt | 0 .../tensors/core/TestDoubleTensorAlgebra.kt | 0 settings.gradle.kts | 1 + 22 files changed, 17 insertions(+), 278 deletions(-) create mode 100644 kmath-tensors/build.gradle.kts rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt (100%) rename {kmath-core => kmath-tensors}/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt (100%) rename {kmath-core => kmath-tensors}/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt (100%) rename {kmath-core => kmath-tensors}/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt (100%) rename {kmath-core => kmath-tensors}/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt (100%) rename {kmath-core => kmath-tensors}/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt (100%) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index cc6c93c20..fee874b12 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -2602,281 +2602,3 @@ public final class space/kscience/kmath/structures/VirtualMutableBuffer : space/ public fun set (ILjava/lang/Object;)V } -public abstract interface class space/kscience/kmath/tensors/AnalyticTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { - public abstract fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun acosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun asin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun asinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun atan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun atanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun ceil (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun cosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun exp (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun floor (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun log (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun sin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun sinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun sqrt (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun tan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun tanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; -} - -public abstract interface class space/kscience/kmath/tensors/LinearOpsTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { - public abstract fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun lu (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; - public abstract fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; - public abstract fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; - public abstract fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; - public abstract fun symEig (Lspace/kscience/kmath/nd/MutableStructureND;Z)Lkotlin/Pair; -} - -public final class space/kscience/kmath/tensors/LinearOpsTensorAlgebra$DefaultImpls { - public static synthetic fun symEig$default (Lspace/kscience/kmath/tensors/LinearOpsTensorAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;ZILjava/lang/Object;)Lkotlin/Pair; -} - -public abstract interface class space/kscience/kmath/tensors/TensorAlgebra { - public abstract fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public abstract fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public abstract fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun times (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public abstract fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public abstract fun transpose (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; - public abstract fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; -} - -public final class space/kscience/kmath/tensors/TensorAlgebra$DefaultImpls { - public static synthetic fun diagonalEmbedding$default (Lspace/kscience/kmath/tensors/TensorAlgebra;Lspace/kscience/kmath/nd/MutableStructureND;IIIILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; -} - -public abstract interface class space/kscience/kmath/tensors/TensorPartialDivisionAlgebra : space/kscience/kmath/tensors/TensorAlgebra { - public abstract fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public abstract fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public abstract fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V -} - -public final class space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra { - public fun ()V - public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun div (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun minus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun plus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun times (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun timesAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V -} - -public final class space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebraKt { - public static final fun BroadcastDoubleTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - -public class space/kscience/kmath/tensors/core/BufferedTensor : space/kscience/kmath/nd/MutableStructureND { - public fun ([ILspace/kscience/kmath/structures/MutableBuffer;I)V - public fun elements ()Lkotlin/sequences/Sequence; - public fun equals (Ljava/lang/Object;)Z - public fun get ([I)Ljava/lang/Object; - public final fun getBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; - public fun getDimension ()I - public final fun getLinearStructure ()Lspace/kscience/kmath/tensors/core/TensorLinearStructure; - public final fun getNumel ()I - public fun getShape ()[I - public fun hashCode ()I - public fun set ([ILjava/lang/Object;)V -} - -public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/AnalyticTensorAlgebra { - public fun ()V - public synthetic fun acos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun acos (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun acosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun acosh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun asin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun asin (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun asinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun asinh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun atan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun atan (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun atanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun atanh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun ceil (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun ceil (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun cos (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cos (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun cosh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cosh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun exp (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun exp (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun floor (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun floor (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun log (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun log (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun sin (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sin (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun sinh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sinh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun sqrt (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun sqrt (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun tan (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun tan (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun tanh (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun tanh (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; -} - -public final class space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebraKt { - public static final fun DoubleAnalyticTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - -public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra : space/kscience/kmath/tensors/core/DoubleTensorAlgebra, space/kscience/kmath/tensors/LinearOpsTensorAlgebra { - public fun ()V - public synthetic fun cholesky (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun cholesky (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun det (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun det (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun detLU (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun inv (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun inv (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun invLU (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun lu (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; - public fun lu (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Pair; - public synthetic fun luPivot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; - public fun luPivot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/IntTensor;)Lkotlin/Triple; - public synthetic fun qr (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Pair; - public fun qr (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Pair; - public synthetic fun svd (Lspace/kscience/kmath/nd/MutableStructureND;)Lkotlin/Triple; - public fun svd (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lkotlin/Triple; - public synthetic fun symEig (Lspace/kscience/kmath/nd/MutableStructureND;Z)Lkotlin/Pair; - public fun symEig (Lspace/kscience/kmath/tensors/core/DoubleTensor;Z)Lkotlin/Pair; -} - -public final class space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebraKt { - public static final fun DoubleLinearOpsTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - -public final class space/kscience/kmath/tensors/core/DoubleTensor : space/kscience/kmath/tensors/core/BufferedTensor { -} - -public class space/kscience/kmath/tensors/core/DoubleTensorAlgebra : space/kscience/kmath/tensors/TensorPartialDivisionAlgebra { - public fun ()V - public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z - public final fun contentEquals (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function2;)Z - public static synthetic fun contentEquals$default (Lspace/kscience/kmath/tensors/core/DoubleTensorAlgebra;Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;DILjava/lang/Object;)Z - public final fun copy (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun diagonalEmbedding (Lspace/kscience/kmath/nd/MutableStructureND;III)Lspace/kscience/kmath/nd/MutableStructureND; - public fun diagonalEmbedding (Lspace/kscience/kmath/tensors/core/DoubleTensor;III)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun div (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun div (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun div (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public synthetic fun divAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V - public fun divAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun dot (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun dot (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Z - public final fun eq (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Z - public final fun eye (I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun fromArray ([I[D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun full (D[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun fullLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun get (Lspace/kscience/kmath/nd/MutableStructureND;I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun get (Lspace/kscience/kmath/tensors/core/DoubleTensor;I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun map (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun minus (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun minus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun minus (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun minus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public synthetic fun minusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V - public fun minusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public final fun ones ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun onesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun plus (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun plus (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun plus (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun plus (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public synthetic fun plusAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V - public fun plusAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public fun times (DLspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/MutableStructureND; - public synthetic fun times (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun times (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public fun times (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Ljava/lang/Object;)V - public synthetic fun timesAssign (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)V - public fun timesAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;D)V - public fun timesAssign (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)V - public synthetic fun transpose (Lspace/kscience/kmath/nd/MutableStructureND;II)Lspace/kscience/kmath/nd/MutableStructureND; - public fun transpose (Lspace/kscience/kmath/tensors/core/DoubleTensor;II)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun unaryMinus (Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun unaryMinus (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun value (Lspace/kscience/kmath/nd/MutableStructureND;)Ljava/lang/Object; - public fun value (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Ljava/lang/Double; - public synthetic fun view (Lspace/kscience/kmath/nd/MutableStructureND;[I)Lspace/kscience/kmath/nd/MutableStructureND; - public fun view (Lspace/kscience/kmath/tensors/core/DoubleTensor;[I)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public synthetic fun viewAs (Lspace/kscience/kmath/nd/MutableStructureND;Lspace/kscience/kmath/nd/MutableStructureND;)Lspace/kscience/kmath/nd/MutableStructureND; - public fun viewAs (Lspace/kscience/kmath/tensors/core/DoubleTensor;Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun zeroesLike (Lspace/kscience/kmath/tensors/core/DoubleTensor;)Lspace/kscience/kmath/tensors/core/DoubleTensor; - public final fun zeros ([I)Lspace/kscience/kmath/tensors/core/DoubleTensor; -} - -public final class space/kscience/kmath/tensors/core/DoubleTensorAlgebraKt { - public static final fun DoubleTensorAlgebra (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - -public final class space/kscience/kmath/tensors/core/FloatTensor : space/kscience/kmath/tensors/core/BufferedTensor { -} - -public final class space/kscience/kmath/tensors/core/IntTensor : space/kscience/kmath/tensors/core/BufferedTensor { -} - -public final class space/kscience/kmath/tensors/core/LongTensor : space/kscience/kmath/tensors/core/BufferedTensor { -} - -public final class space/kscience/kmath/tensors/core/TensorLinearStructure { - public fun ([I)V - public final fun getShape ()[I - public final fun getSize ()I - public final fun getStrides ()[I - public final fun index (I)[I - public final fun indices ()Lkotlin/sequences/Sequence; - public final fun offset ([I)I - public final fun stepIndex ([I)[I -} - diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts new file mode 100644 index 000000000..8e823416b --- /dev/null +++ b/kmath-tensors/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + id("ru.mipt.npm.gradle.mpp") +} + +kotlin.sourceSets { + commonMain { + dependencies { + api(project(":kmath-core")) + api(project(":kmath-stat")) + } + } +} + +readme { + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt similarity index 100% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt similarity index 100% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt rename to kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt rename to kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt similarity index 100% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt rename to kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt similarity index 100% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt rename to kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt similarity index 100% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt rename to kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt diff --git a/settings.gradle.kts b/settings.gradle.kts index 4467d5ed6..ffc93d576 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -40,5 +40,6 @@ include( ":kmath-ast", ":kmath-ejml", ":kmath-kotlingrad", + ":kmath-tensors", ":examples" ) From 706a44fd3300f050115e4b40042fe32046b181e0 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 31 Mar 2021 09:15:55 +0100 Subject: [PATCH 159/393] get normals TBD --- .../space/kscience/kmath/tensors/core/utils.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index d8a073d64..e46d39cf2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.samplers.BoxMullerNormalizedGaussianSampler import space.kscience.kmath.structures.* import kotlin.random.Random import kotlin.math.* @@ -35,8 +37,10 @@ internal fun Buffer.array(): DoubleArray = when (this) { is DoubleBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") } - -internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { - val u = Random(seed) - return (0 until n).map { sqrt(-2.0 * ln(u.nextDouble())) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() +/* +internal inline fun getRandomNormals(n: Int,): DoubleArray { + val sampler = BoxMullerNormalizedGaussianSampler.of() + val chain = sampler.sample(RandomGenerator.default) + return (0 until n).map { chain.next() }.toDoubleArray() } +*/ \ No newline at end of file From b36281fa39d810ae1e60d2e7a9e042be754b8687 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 31 Mar 2021 09:23:41 +0100 Subject: [PATCH 160/393] roll back --- .../space/kscience/kmath/tensors/core/utils.kt | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index e46d39cf2..fc0ebe7fa 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -37,10 +37,8 @@ internal fun Buffer.array(): DoubleArray = when (this) { is DoubleBuffer -> array else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") } -/* -internal inline fun getRandomNormals(n: Int,): DoubleArray { - val sampler = BoxMullerNormalizedGaussianSampler.of() - val chain = sampler.sample(RandomGenerator.default) - return (0 until n).map { chain.next() }.toDoubleArray() -} -*/ \ No newline at end of file + +internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { + val u = Random(seed) + return (0 until n).map { sqrt(-2.0 * ln(u.nextDouble())) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() +} \ No newline at end of file From 9ee506b1d2996b3d46ea569e03d3a1862e4c1dff Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 25 Mar 2021 23:57:47 +0700 Subject: [PATCH 161/393] Some experiments with MST rendering --- README.md | 4 +- .../space/kscience/kmath/ast/astRendering.kt | 21 ++ kmath-ast/README.md | 42 ++- kmath-ast/docs/README-TEMPLATE.md | 36 ++ .../ast/rendering/LatexSyntaxRenderer.kt | 128 +++++++ .../ast/rendering/MathMLSyntaxRenderer.kt | 133 +++++++ .../kmath/ast/rendering/MathRenderer.kt | 102 ++++++ .../kmath/ast/rendering/MathSyntax.kt | 326 ++++++++++++++++++ .../kmath/ast/rendering/SyntaxRenderer.kt | 25 ++ .../kscience/kmath/ast/rendering/features.kt | 312 +++++++++++++++++ .../kscience/kmath/ast/rendering/stages.kt | 197 +++++++++++ .../space/kscience/kmath/estree/estree.kt | 4 +- .../kotlin/space/kscience/kmath/asm/asm.kt | 4 +- .../kotlin/space/kscience/kmath/ast/parser.kt | 3 +- .../kmath/ast/rendering/TestFeatures.kt | 90 +++++ .../kscience/kmath/ast/rendering/TestLatex.kt | 65 ++++ .../kmath/ast/rendering/TestMathML.kt | 84 +++++ .../kmath/ast/rendering/TestStages.kt | 28 ++ .../kscience/kmath/ast/rendering/TestUtils.kt | 41 +++ kmath-complex/README.md | 6 +- kmath-core/README.md | 6 +- .../space/kscience/kmath/operations/BigInt.kt | 3 +- kmath-ejml/README.md | 6 +- kmath-for-real/README.md | 6 +- kmath-functions/README.md | 6 +- kmath-nd4j/README.md | 6 +- 26 files changed, 1655 insertions(+), 29 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt create mode 100644 kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt create mode 100644 kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt create mode 100644 kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt create mode 100644 kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt create mode 100644 kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt create mode 100644 kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt create mode 100644 kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt create mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt create mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt create mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt create mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt create mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt diff --git a/README.md b/README.md index 7080c757e..7b78d4531 100644 --- a/README.md +++ b/README.md @@ -259,8 +259,8 @@ repositories { } dependencies { - api("space.kscience:kmath-core:0.3.0-dev-3") - // api("kscience.kmath:kmath-core-jvm:0.3.0-dev-3") for jvm-specific version + api("space.kscience:kmath-core:0.3.0-dev-4") + // api("kscience.kmath:kmath-core-jvm:0.3.0-dev-4") for jvm-specific version } ``` diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt new file mode 100644 index 000000000..a250ad800 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt @@ -0,0 +1,21 @@ +package space.kscience.kmath.ast + +import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess +import space.kscience.kmath.ast.rendering.LatexSyntaxRenderer +import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer +import space.kscience.kmath.ast.rendering.renderWithStringBuilder + +public fun main() { + val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath() + val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst) + println("MathSyntax:") + println(syntax) + println() + val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax) + println("LaTeX:") + println(latex) + println() + val mathML = MathMLSyntaxRenderer.renderWithStringBuilder(syntax) + println("MathML:") + println(mathML) +} diff --git a/kmath-ast/README.md b/kmath-ast/README.md index ff954b914..44faa5cd5 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -12,7 +12,7 @@ Abstract syntax tree expression representation and related optimizations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-3`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-4`. **Gradle:** ```gradle @@ -23,7 +23,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0-dev-3' + implementation 'space.kscience:kmath-ast:0.3.0-dev-4' } ``` **Gradle Kotlin DSL:** @@ -35,7 +35,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0-dev-3") + implementation("space.kscience:kmath-ast:0.3.0-dev-4") } ``` @@ -111,3 +111,39 @@ var executable = function (constants, arguments) { #### Known issues - This feature uses `eval` which can be unavailable in several environments. + +## Rendering expressions + +kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax. + +Example usage: + +```kotlin +import space.kscience.kmath.ast.* +import space.kscience.kmath.ast.rendering.* + +public fun main() { + val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath() + val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst) + val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax) + println("LaTeX:") + println(latex) + println() + val mathML = MathMLSyntaxRenderer.renderWithStringBuilder(syntax) + println("MathML:") + println(mathML) +} +``` + +Result LaTeX: + +![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D) + +Result MathML (embedding MathML is not allowed by GitHub Markdown): + +```html +ex-sin-12x2×1010+x3-12 +``` + +It is also possible to create custom algorithms of render, and even add support of other markup languages +(see API reference). diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index db071adb4..9ed44d584 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -78,3 +78,39 @@ var executable = function (constants, arguments) { #### Known issues - This feature uses `eval` which can be unavailable in several environments. + +## Rendering expressions + +kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax. + +Example usage: + +```kotlin +import space.kscience.kmath.ast.* +import space.kscience.kmath.ast.rendering.* + +public fun main() { + val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath() + val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst) + val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax) + println("LaTeX:") + println(latex) + println() + val mathML = MathMLSyntaxRenderer.renderWithStringBuilder(syntax) + println("MathML:") + println(mathML) +} +``` + +Result LaTeX: + +![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D) + +Result MathML (embedding MathML is not allowed by GitHub Markdown): + +```html +ex-sin-12x2×1010+x3-12 +``` + +It is also possible to create custom algorithms of render, and even add support of other markup languages +(see API reference). diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt new file mode 100644 index 000000000..914da6d9f --- /dev/null +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -0,0 +1,128 @@ +package space.kscience.kmath.ast.rendering + +/** + * [SyntaxRenderer] implementation for LaTeX. + * + * The generated string is a valid LaTeX fragment to be used in the Math Mode. + * + * Example usage: + * + * ``` + * \documentclass{article} + * \begin{document} + * \begin{equation} + * %code generated by the syntax renderer + * \end{equation} + * \end{document} + * ``` + * + * @author Iaroslav Postovalov + */ +public object LatexSyntaxRenderer : SyntaxRenderer { + public override fun render(node: MathSyntax, output: Appendable): Unit = output.run { + fun render(syntax: MathSyntax) = render(syntax, output) + + when (node) { + is NumberSyntax -> append(node.string) + is SymbolSyntax -> append(node.string) + + is OperatorNameSyntax -> { + append("\\operatorname{") + append(node.name) + append('}') + } + + is SpecialSymbolSyntax -> when (node.kind) { + SpecialSymbolSyntax.Kind.INFINITY -> append("\\infty") + } + + is OperandSyntax -> { + if (node.parentheses) append("\\left(") + render(node.operand) + if (node.parentheses) append("\\right)") + } + + is UnaryOperatorSyntax -> { + render(node.prefix) + append("\\,") + render(node.operand) + } + + is UnaryPlusSyntax -> { + append('+') + render(node.operand) + } + + is UnaryMinusSyntax -> { + append('-') + render(node.operand) + } + + is RadicalSyntax -> { + append("\\sqrt") + append('{') + render(node.operand) + append('}') + } + + is SuperscriptSyntax -> { + render(node.left) + append("^{") + render(node.right) + append('}') + } + + is SubscriptSyntax -> { + render(node.left) + append("_{") + render(node.right) + append('}') + } + + is BinaryOperatorSyntax -> { + render(node.prefix) + append("\\left(") + render(node.left) + append(',') + render(node.right) + append("\\right)") + } + + is BinaryPlusSyntax -> { + render(node.left) + append('+') + render(node.right) + } + + is BinaryMinusSyntax -> { + render(node.left) + append('-') + render(node.right) + } + + is FractionSyntax -> { + append("\\frac{") + render(node.left) + append("}{") + render(node.right) + append('}') + } + + is RadicalWithIndexSyntax -> { + append("\\sqrt") + append('[') + render(node.left) + append(']') + append('{') + render(node.right) + append('}') + } + + is MultiplicationSyntax -> { + render(node.left) + append(if (node.times) "\\times" else "\\,") + render(node.right) + } + } + } +} diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt new file mode 100644 index 000000000..6f194be86 --- /dev/null +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -0,0 +1,133 @@ +package space.kscience.kmath.ast.rendering + +/** + * [SyntaxRenderer] implementation for MathML. + * + * The generated XML string is a valid MathML instance. + * + * @author Iaroslav Postovalov + */ +public object MathMLSyntaxRenderer : SyntaxRenderer { + public override fun render(node: MathSyntax, output: Appendable) { + output.append("") + render0(node, output) + output.append("") + } + + private fun render0(node: MathSyntax, output: Appendable): Unit = output.run { + fun tag(tagName: String, vararg attr: Pair, block: () -> Unit = {}) { + append('<') + append(tagName) + + if (attr.isNotEmpty()) { + append(' ') + var count = 0 + + for ((name, value) in attr) { + if (++count > 1) append(' ') + append(name) + append("=\"") + append(value) + append('"') + } + } + + append('>') + block() + append("') + } + + fun render(syntax: MathSyntax) = render0(syntax, output) + + when (node) { + is NumberSyntax -> tag("mn") { append(node.string) } + is SymbolSyntax -> tag("mi") { append(node.string) } + is OperatorNameSyntax -> tag("mo") { append(node.name) } + + is SpecialSymbolSyntax -> when (node.kind) { + SpecialSymbolSyntax.Kind.INFINITY -> tag("mo") { append("∞") } + } + + is OperandSyntax -> if (node.parentheses) { + tag("mfenced", "open" to "(", "close" to ")", "separators" to "") { + render(node.operand) + } + } else { + render(node.operand) + } + + is UnaryOperatorSyntax -> { + render(node.prefix) + tag("mspace", "width" to "0.167em") + render(node.operand) + } + + is UnaryPlusSyntax -> { + tag("mo") { append('+') } + render(node.operand) + } + + is UnaryMinusSyntax -> { + tag("mo") { append("-") } + render(node.operand) + } + + is RadicalSyntax -> tag("msqrt") { render(node.operand) } + + is SuperscriptSyntax -> tag("msup") { + tag("mrow") { render(node.left) } + tag("mrow") { render(node.right) } + } + + is SubscriptSyntax -> tag("msub") { + tag("mrow") { render(node.left) } + tag("mrow") { render(node.right) } + } + + is BinaryOperatorSyntax -> { + render(node.prefix) + + tag("mfenced", "open" to "(", "close" to ")", "separators" to "") { + render(node.left) + tag("mo") { append(',') } + render(node.right) + } + } + + is BinaryPlusSyntax -> { + render(node.left) + tag("mo") { append('+') } + render(node.right) + } + + is BinaryMinusSyntax -> { + render(node.left) + tag("mo") { append('-') } + render(node.right) + } + + is FractionSyntax -> tag("mfrac") { + tag("mrow") { + render(node.left) + } + + tag("mrow") { + render(node.right) + } + } + + is RadicalWithIndexSyntax -> tag("mroot") { + tag("mrow") { render(node.right) } + tag("mrow") { render(node.left) } + } + + is MultiplicationSyntax -> { + render(node.left) + if (node.times) tag("mo") { append("×") } else tag("mspace", "width" to "0.167em") + render(node.right) + } + } + } +} diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt new file mode 100644 index 000000000..afdf12b04 --- /dev/null +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -0,0 +1,102 @@ +package space.kscience.kmath.ast.rendering + +import space.kscience.kmath.ast.MST + +/** + * Renders [MST] to [MathSyntax]. + * + * @author Iaroslav Postovalov + */ +public fun interface MathRenderer { + /** + * Renders [MST] to [MathSyntax]. + */ + public fun render(mst: MST): MathSyntax +} + +/** + * Implements [MST] render process with sequence of features. + * + * @property features The applied features. + * @author Iaroslav Postovalov + */ +public open class FeaturedMathRenderer(public val features: List) : MathRenderer { + public override fun render(mst: MST): MathSyntax { + for (feature in features) feature.render(this, mst)?.let { return it } + throw UnsupportedOperationException("Renderer $this has no appropriate feature to render node $mst.") + } + + /** + * Logical unit of [MST] rendering. + */ + public fun interface RenderFeature { + /** + * Renders [MST] to [MathSyntax] in the context of owning renderer. + */ + public fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? + } +} + +/** + * Extends [FeaturedMathRenderer] by adding post-processing stages. + * + * @property stages The applied stages. + * @author Iaroslav Postovalov + */ +public open class FeaturedMathRendererWithPostProcess( + features: List, + public val stages: List, +) : FeaturedMathRenderer(features) { + public override fun render(mst: MST): MathSyntax { + val res = super.render(mst) + for (stage in stages) stage.perform(res) + return res + } + + /** + * Logical unit of [MathSyntax] post-processing. + */ + public fun interface PostProcessStage { + /** + * Performs the specified action over [MathSyntax]. + */ + public fun perform(node: MathSyntax) + } + + public companion object { + /** + * The default setup of [FeaturedMathRendererWithPostProcess]. + */ + public val Default: FeaturedMathRendererWithPostProcess = FeaturedMathRendererWithPostProcess( + listOf( + // Printing known operations + BinaryPlus.Default, + BinaryMinus.Default, + UnaryPlus.Default, + UnaryMinus.Default, + Multiplication.Default, + Fraction.Default, + Power.Default, + SquareRoot.Default, + Exponential.Default, + InverseTrigonometricOperations.Default, + + // Fallback option for unknown operations - printing them as operator + BinaryOperator.Default, + UnaryOperator.Default, + + // Pretty printing for numerics + PrettyPrintFloats.Default, + PrettyPrintIntegers.Default, + + // Printing terminal nodes as string + PrintNumeric, + PrintSymbolic, + ), + listOf( + SimplifyParentheses.Default, + BetterMultiplication, + ) + ) + } +} diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt new file mode 100644 index 000000000..4c85adcfc --- /dev/null +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -0,0 +1,326 @@ +package space.kscience.kmath.ast.rendering + +/** + * Mathematical typography syntax node. + * + * @author Iaroslav Postovalov + */ +public sealed class MathSyntax { + /** + * The parent node of this syntax node. + */ + public var parent: MathSyntax? = null +} + +/** + * Terminal node, which should not have any children nodes. + * + * @author Iaroslav Postovalov + */ +public sealed class TerminalSyntax : MathSyntax() + +/** + * Node containing a certain operation. + * + * @author Iaroslav Postovalov + */ +public sealed class OperationSyntax : MathSyntax() { + /** + * The operation token. + */ + public abstract val operation: String +} + +/** + * Unary node, which has only one child. + * + * @author Iaroslav Postovalov + */ +public sealed class UnarySyntax : OperationSyntax() { + /** + * The operand of this node. + */ + public abstract val operand: MathSyntax +} + +/** + * Binary node, which has only two children. + * + * @author Iaroslav Postovalov + */ +public sealed class BinarySyntax : OperationSyntax() { + /** + * The left-hand side operand. + */ + public abstract val left: MathSyntax + + /** + * The right-hand side operand. + */ + public abstract val right: MathSyntax +} + +/** + * Represents a number. + * + * @property string The digits of number. + * @author Iaroslav Postovalov + */ +public data class NumberSyntax(public var string: String) : TerminalSyntax() + +/** + * Represents a symbol. + * + * @property string The symbol. + * @author Iaroslav Postovalov + */ +public data class SymbolSyntax(public var string: String) : TerminalSyntax() + +/** + * Represents special typing for operator name. + * + * @property name The operator name. + * @see BinaryOperatorSyntax + * @see UnaryOperatorSyntax + * @author Iaroslav Postovalov + */ +public data class OperatorNameSyntax(public var name: String) : TerminalSyntax() + +/** + * Represents a usage of special symbols. + * + * @property kind The kind of symbol. + * @author Iaroslav Postovalov + */ +public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() { + /** + * The kind of symbol. + */ + public enum class Kind { + /** + * The infinity (∞) symbol. + */ + INFINITY, + } +} + +/** + * Represents operand of a certain operator wrapped with parentheses or not. + * + * @property operand The operand. + * @property parentheses Whether the operand should be wrapped with parentheses. + * @author Iaroslav Postovalov + */ +public data class OperandSyntax( + public val operand: MathSyntax, + public var parentheses: Boolean, +) : MathSyntax() { + init { + operand.parent = this + } +} + +/** + * Represents unary, prefix operator syntax (like f x). + * + * @property prefix The prefix. + * @author Iaroslav Postovalov + */ +public data class UnaryOperatorSyntax( + public override val operation: String, + public var prefix: MathSyntax, + public override val operand: OperandSyntax, +) : UnarySyntax() { + init { + operand.parent = this + } +} + +/** + * Represents prefix, unary plus operator. + * + * @author Iaroslav Postovalov + */ +public data class UnaryPlusSyntax( + public override val operation: String, + public override val operand: OperandSyntax, +) : UnarySyntax() { + init { + operand.parent = this + } +} + +/** + * Represents prefix, unary minus operator. + * + * @author Iaroslav Postovalov + */ +public data class UnaryMinusSyntax( + public override val operation: String, + public override val operand: OperandSyntax, +) : UnarySyntax() { + init { + operand.parent = this + } +} + +/** + * Represents radical with a node inside it. + * + * @property operand The radicand. + * @author Iaroslav Postovalov + */ +public data class RadicalSyntax( + public override val operation: String, + public override val operand: MathSyntax, +) : UnarySyntax() { + init { + operand.parent = this + } +} + +/** + * Represents a syntax node with superscript (usually, for exponentiation). + * + * @property left The node. + * @property right The superscript. + * @author Iaroslav Postovalov + */ +public data class SuperscriptSyntax( + public override val operation: String, + public override val left: MathSyntax, + public override val right: MathSyntax, +) : BinarySyntax() { + init { + left.parent = this + right.parent = this + } +} + +/** + * Represents a syntax node with subscript. + * + * @property left The node. + * @property right The subscript. + * @author Iaroslav Postovalov + */ +public data class SubscriptSyntax( + public override val operation: String, + public override val left: MathSyntax, + public override val right: MathSyntax, +) : BinarySyntax() { + init { + left.parent = this + right.parent = this + } +} + +/** + * Represents binary, prefix operator syntax (like f(a, b)). + * + * @property prefix The prefix. + * @author Iaroslav Postovalov + */ +public data class BinaryOperatorSyntax( + public override val operation: String, + public var prefix: MathSyntax, + public override val left: MathSyntax, + public override val right: MathSyntax, +) : BinarySyntax() { + init { + left.parent = this + right.parent = this + } +} + +/** + * Represents binary, infix addition. + * + * @param left The augend. + * @param right The addend. + * @author Iaroslav Postovalov + */ +public data class BinaryPlusSyntax( + public override val operation: String, + public override val left: OperandSyntax, + public override val right: OperandSyntax, +) : BinarySyntax() { + init { + left.parent = this + right.parent = this + } +} + +/** + * Represents binary, infix subtraction. + * + * @param left The minuend. + * @param right The subtrahend. + * @author Iaroslav Postovalov + */ +public data class BinaryMinusSyntax( + public override val operation: String, + public override val left: OperandSyntax, + public override val right: OperandSyntax, +) : BinarySyntax() { + init { + left.parent = this + right.parent = this + } +} + +/** + * Represents fraction with numerator and denominator. + * + * @property left The numerator. + * @property right The denominator. + * @author Iaroslav Postovalov + */ +public data class FractionSyntax( + public override val operation: String, + public override val left: MathSyntax, + public override val right: MathSyntax, +) : BinarySyntax() { + init { + left.parent = this + right.parent = this + } +} + +/** + * Represents radical syntax with index. + * + * @property left The index. + * @property right The radicand. + * @author Iaroslav Postovalov + */ +public data class RadicalWithIndexSyntax( + public override val operation: String, + public override val left: MathSyntax, + public override val right: MathSyntax, +) : BinarySyntax() { + init { + left.parent = this + right.parent = this + } +} + +/** + * Represents binary, infix multiplication in the form of coefficient (2 x) or with operator (x×2). + * + * @property left The multiplicand. + * @property right The multiplier. + * @property times whether the times (×) symbol should be used. + * @author Iaroslav Postovalov + */ +public data class MultiplicationSyntax( + public override val operation: String, + public override val left: OperandSyntax, + public override val right: OperandSyntax, + public var times: Boolean, +) : BinarySyntax() { + init { + left.parent = this + right.parent = this + } +} diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt new file mode 100644 index 000000000..fcc79f76b --- /dev/null +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt @@ -0,0 +1,25 @@ +package space.kscience.kmath.ast.rendering + +/** + * Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should + * involve traversal of MathSyntax with handling each its subtype. + * + * @author Iaroslav Postovalov + */ +public fun interface SyntaxRenderer { + /** + * Renders the [MathSyntax] to [output]. + */ + public fun render(node: MathSyntax, output: Appendable) +} + +/** + * Calls [SyntaxRenderer.render] with given [node] and a new [StringBuilder] instance, and returns its content. + * + * @author Iaroslav Postovalov + */ +public fun SyntaxRenderer.renderWithStringBuilder(node: MathSyntax): String { + val sb = StringBuilder() + render(node, sb) + return sb.toString() +} diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt new file mode 100644 index 000000000..6e66d3ca3 --- /dev/null +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -0,0 +1,312 @@ +package space.kscience.kmath.ast.rendering + +import space.kscience.kmath.ast.MST +import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature +import space.kscience.kmath.operations.* +import kotlin.reflect.KClass + +/** + * Prints any [MST.Symbolic] as a [SymbolSyntax] containing the [MST.Symbolic.value] of it. + * + * @author Iaroslav Postovalov + */ +public object PrintSymbolic : RenderFeature { + public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { + if (node !is MST.Symbolic) return null + return SymbolSyntax(string = node.value) + } +} + +/** + * Prints any [MST.Numeric] as a [NumberSyntax] containing the [Any.toString] result of it. + * + * @author Iaroslav Postovalov + */ +public object PrintNumeric : RenderFeature { + public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { + if (node !is MST.Numeric) return null + return NumberSyntax(string = node.value.toString()) + } +} + +private fun printSignedNumberString(s: String): MathSyntax { + if (s.startsWith('-')) + return UnaryMinusSyntax( + operation = GroupOperations.MINUS_OPERATION, + operand = OperandSyntax( + operand = NumberSyntax(string = s.removePrefix("-")), + parentheses = true, + ), + ) + + return NumberSyntax(string = s) +} + +/** + * Special printing for numeric types which are printed in form of + * *('-'? (DIGIT+ ('.' DIGIT+)? ('E' '-'? DIGIT+)? | 'Infinity')) | 'NaN'*. + * + * @property types The suitable types. + */ +public class PrettyPrintFloats(public val types: Set>) : RenderFeature { + public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { + if (node !is MST.Numeric || node.value::class !in types) return null + val toString = node.value.toString().removeSuffix(".0") + + if ('E' in toString) { + val (beforeE, afterE) = toString.split('E') + val significand = beforeE.toDouble().toString().removeSuffix(".0") + val exponent = afterE.toDouble().toString().removeSuffix(".0") + + return MultiplicationSyntax( + operation = RingOperations.TIMES_OPERATION, + left = OperandSyntax(operand = NumberSyntax(significand), parentheses = true), + right = OperandSyntax( + operand = SuperscriptSyntax( + operation = PowerOperations.POW_OPERATION, + left = NumberSyntax(string = "10"), + right = printSignedNumberString(exponent), + ), + parentheses = true, + ), + times = true, + ) + } + + if (toString.endsWith("Infinity")) { + val infty = SpecialSymbolSyntax(SpecialSymbolSyntax.Kind.INFINITY) + + if (toString.startsWith('-')) + return UnaryMinusSyntax( + operation = GroupOperations.MINUS_OPERATION, + operand = OperandSyntax(operand = infty, parentheses = true), + ) + + return infty + } + + return printSignedNumberString(toString) + } + + public companion object { + /** + * The default instance containing [Float], and [Double]. + */ + public val Default: PrettyPrintFloats = PrettyPrintFloats(setOf(Float::class, Double::class)) + } +} + +/** + * Special printing for numeric types which are printed in form of *'-'? DIGIT+*. + * + * @property types The suitable types. + */ +public class PrettyPrintIntegers(public val types: Set>) : RenderFeature { + public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { + if (node !is MST.Numeric || node.value::class !in types) + return null + + return printSignedNumberString(node.value.toString()) + } + + public companion object { + /** + * The default instance containing [Byte], [Short], [Int], and [Long]. + */ + public val Default: PrettyPrintIntegers = + PrettyPrintIntegers(setOf(Byte::class, Short::class, Int::class, Long::class)) + } +} + +/** + * Abstract printing of unary operations which discards [MST] if their operation is not in [operations] or its type is + * not [MST.Unary]. + * + * @param operations the allowed operations. If `null`, any operation is accepted. + */ +public abstract class Unary(public val operations: Collection?) : RenderFeature { + /** + * The actual render function. + */ + protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax? + + public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { + if (node !is MST.Unary || operations != null && node.operation !in operations) return null + return render0(renderer, node) + } +} + +/** + * Abstract printing of unary operations which discards [MST] if their operation is not in [operations] or its type is + * not [MST.Binary]. + * + * @property operations the allowed operations. If `null`, any operation is accepted. + */ +public abstract class Binary(public val operations: Collection?) : RenderFeature { + /** + * The actual render function. + */ + protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax? + + public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { + if (node !is MST.Binary || operations != null && node.operation !in operations) return null + return render0(renderer, node) + } +} + +public class BinaryPlus(operations: Collection?) : Binary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryPlusSyntax( + operation = node.operation, + left = OperandSyntax(parent.render(node.left), true), + right = OperandSyntax(parent.render(node.right), true), + ) + + public companion object { + public val Default: BinaryPlus = BinaryPlus(setOf(GroupOperations.PLUS_OPERATION)) + } +} + +public class BinaryMinus(operations: Collection?) : Binary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryMinusSyntax( + operation = node.operation, + left = OperandSyntax(operand = parent.render(node.left), parentheses = true), + right = OperandSyntax(operand = parent.render(node.right), parentheses = true), + ) + + public companion object { + public val Default: BinaryMinus = BinaryMinus(setOf(GroupOperations.MINUS_OPERATION)) + } +} + +public class UnaryPlus(operations: Collection?) : Unary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax( + operation = node.operation, + operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), + ) + + public companion object { + public val Default: UnaryPlus = UnaryPlus(setOf(GroupOperations.PLUS_OPERATION)) + } +} + +public class UnaryMinus(operations: Collection?) : Unary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax( + operation = node.operation, + operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), + ) + + public companion object { + public val Default: UnaryMinus = UnaryMinus(setOf(GroupOperations.MINUS_OPERATION)) + } +} + +public class Fraction(operations: Collection?) : Binary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax( + operation = node.operation, + left = parent.render(node.left), + right = parent.render(node.right), + ) + + public companion object { + public val Default: Fraction = Fraction(setOf(FieldOperations.DIV_OPERATION)) + } +} + +public class BinaryOperator(operations: Collection?) : Binary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryOperatorSyntax( + operation = node.operation, + prefix = OperatorNameSyntax(name = node.operation), + left = parent.render(node.left), + right = parent.render(node.right), + ) + + public companion object { + public val Default: BinaryOperator = BinaryOperator(null) + } +} + +public class UnaryOperator(operations: Collection?) : Unary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( + operation = node.operation, + prefix = OperatorNameSyntax(node.operation), + operand = OperandSyntax(parent.render(node.value), true), + ) + + public companion object { + public val Default: UnaryOperator = UnaryOperator(null) + } +} + +public class Power(operations: Collection?) : Binary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = SuperscriptSyntax( + operation = node.operation, + left = OperandSyntax(parent.render(node.left), true), + right = OperandSyntax(parent.render(node.right), true), + ) + + public companion object { + public val Default: Power = Power(setOf(PowerOperations.POW_OPERATION)) + } +} + +public class SquareRoot(operations: Collection?) : Unary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = + RadicalSyntax(operation = node.operation, operand = parent.render(node.value)) + + public companion object { + public val Default: SquareRoot = SquareRoot(setOf(PowerOperations.SQRT_OPERATION)) + } +} + +public class Exponential(operations: Collection?) : Unary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = SuperscriptSyntax( + operation = node.operation, + left = SymbolSyntax(string = "e"), + right = parent.render(node.value), + ) + + public companion object { + public val Default: Exponential = Exponential(setOf(ExponentialOperations.EXP_OPERATION)) + } +} + +public class Multiplication(operations: Collection?) : Binary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = MultiplicationSyntax( + operation = node.operation, + left = OperandSyntax(operand = parent.render(node.left), parentheses = true), + right = OperandSyntax(operand = parent.render(node.right), parentheses = true), + times = true, + ) + + public companion object { + public val Default: Multiplication = Multiplication(setOf( + RingOperations.TIMES_OPERATION, + )) + } +} + +public class InverseTrigonometricOperations(operations: Collection?) : Unary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( + operation = node.operation, + prefix = SuperscriptSyntax( + operation = PowerOperations.POW_OPERATION, + left = OperatorNameSyntax(name = node.operation.removePrefix("a")), + right = UnaryMinusSyntax( + operation = GroupOperations.MINUS_OPERATION, + operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true), + ), + ), + operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), + ) + + public companion object { + public val Default: InverseTrigonometricOperations = InverseTrigonometricOperations(setOf( + TrigonometricOperations.ACOS_OPERATION, + TrigonometricOperations.ASIN_OPERATION, + TrigonometricOperations.ATAN_OPERATION, + ExponentialOperations.ACOSH_OPERATION, + ExponentialOperations.ASINH_OPERATION, + ExponentialOperations.ATANH_OPERATION, + )) + } +} diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt new file mode 100644 index 000000000..c183f6ace --- /dev/null +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt @@ -0,0 +1,197 @@ +package space.kscience.kmath.ast.rendering + +import space.kscience.kmath.operations.FieldOperations +import space.kscience.kmath.operations.GroupOperations +import space.kscience.kmath.operations.PowerOperations +import space.kscience.kmath.operations.RingOperations + +/** + * Removes unnecessary times (×) symbols from [MultiplicationSyntax]. + * + * @author Iaroslav Postovalov + */ +public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage { + public override fun perform(node: MathSyntax) { + when (node) { + is NumberSyntax -> Unit + is SymbolSyntax -> Unit + is OperatorNameSyntax -> Unit + is SpecialSymbolSyntax -> Unit + is OperandSyntax -> perform(node.operand) + + is UnaryOperatorSyntax -> { + perform(node.prefix) + perform(node.operand) + } + + is UnaryPlusSyntax -> perform(node.operand) + is UnaryMinusSyntax -> perform(node.operand) + is RadicalSyntax -> perform(node.operand) + + is SuperscriptSyntax -> { + perform(node.left) + perform(node.right) + } + + is SubscriptSyntax -> { + perform(node.left) + perform(node.right) + } + + is BinaryOperatorSyntax -> { + perform(node.prefix) + perform(node.left) + perform(node.right) + } + + is BinaryPlusSyntax -> { + perform(node.left) + perform(node.right) + } + + is BinaryMinusSyntax -> { + perform(node.left) + perform(node.right) + } + + is FractionSyntax -> { + perform(node.left) + perform(node.right) + } + + is RadicalWithIndexSyntax -> { + perform(node.left) + perform(node.right) + } + + is MultiplicationSyntax -> { + node.times = node.right.operand is NumberSyntax && !node.right.parentheses + || node.left.operand is NumberSyntax && node.right.operand is FractionSyntax + || node.left.operand is NumberSyntax && node.right.operand is NumberSyntax + || node.left.operand is NumberSyntax && node.right.operand is SuperscriptSyntax && node.right.operand.left is NumberSyntax + + perform(node.left) + perform(node.right) + } + } + } +} + +/** + * Removes unnecessary parentheses from [OperandSyntax]. + * + * @property precedenceFunction Returns the precedence number for syntax node. Higher number is lower priority. + * @author Iaroslav Postovalov + */ +public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) : + FeaturedMathRendererWithPostProcess.PostProcessStage { + public override fun perform(node: MathSyntax) { + when (node) { + is NumberSyntax -> Unit + is SymbolSyntax -> Unit + is OperatorNameSyntax -> Unit + is SpecialSymbolSyntax -> Unit + + is OperandSyntax -> { + val isRightOfSuperscript = + (node.parent is SuperscriptSyntax) && (node.parent as SuperscriptSyntax).right === node + + val precedence = precedenceFunction(node.operand) + + val needParenthesesByPrecedence = when (val parent = node.parent) { + null -> false + + is BinarySyntax -> { + val parentPrecedence = precedenceFunction(parent) + + parentPrecedence < precedence || + parentPrecedence == precedence && parentPrecedence != 0 && node === parent.right + } + + else -> precedence > precedenceFunction(parent) + } + + node.parentheses = !isRightOfSuperscript + && (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax) + + perform(node.operand) + } + + is UnaryOperatorSyntax -> { + perform(node.prefix) + perform(node.operand) + } + + is UnaryPlusSyntax -> perform(node.operand) + is UnaryMinusSyntax -> { + perform(node.operand) + } + is RadicalSyntax -> perform(node.operand) + + is SuperscriptSyntax -> { + perform(node.left) + perform(node.right) + } + + is SubscriptSyntax -> { + perform(node.left) + perform(node.right) + } + + is BinaryOperatorSyntax -> { + perform(node.prefix) + perform(node.left) + perform(node.right) + } + + is BinaryPlusSyntax -> { + perform(node.left) + perform(node.right) + } + + is BinaryMinusSyntax -> { + perform(node.left) + perform(node.right) + } + + is FractionSyntax -> { + perform(node.left) + perform(node.right) + } + + is MultiplicationSyntax -> { + perform(node.left) + perform(node.right) + } + + is RadicalWithIndexSyntax -> { + perform(node.left) + perform(node.right) + } + } + } + + public companion object { + /** + * The default configuration of [SimplifyParentheses] where power is 1, multiplicative operations are 2, + * additive operations are 3. + */ + public val Default: SimplifyParentheses = SimplifyParentheses { + when (it) { + is TerminalSyntax -> 0 + is UnarySyntax -> 2 + + is BinarySyntax -> when (it.operation) { + PowerOperations.POW_OPERATION -> 1 + RingOperations.TIMES_OPERATION -> 3 + FieldOperations.DIV_OPERATION -> 3 + GroupOperations.MINUS_OPERATION -> 4 + GroupOperations.PLUS_OPERATION -> 4 + else -> 0 + } + + else -> 0 + } + } + } +} diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt index 0bd9a386d..456a2ba07 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt @@ -68,7 +68,7 @@ internal fun MST.compileWith(algebra: Algebra): Expression { /** * Compiles an [MST] to ESTree generated expression using given algebra. * - * @author Alexander Nozik. + * @author Iaroslav Postovalov */ public fun Algebra.expression(mst: MST): Expression = mst.compileWith(this) @@ -76,7 +76,7 @@ public fun Algebra.expression(mst: MST): Expression = /** * Optimizes performance of an [MstExpression] by compiling it into ESTree generated expression. * - * @author Alexander Nozik. + * @author Iaroslav Postovalov */ public fun MstExpression>.compile(): Expression = mst.compileWith(algebra) diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt index 8875bd715..369fe136b 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt @@ -73,7 +73,7 @@ internal fun MST.compileWith(type: Class, algebra: Algebra): Exp /** * Compiles an [MST] to ASM using given algebra. * - * @author Alexander Nozik. + * @author Alexander Nozik */ public inline fun Algebra.expression(mst: MST): Expression = mst.compileWith(T::class.java, this) @@ -81,7 +81,7 @@ public inline fun Algebra.expression(mst: MST): Expression< /** * Optimizes performance of an [MstExpression] using ASM codegen. * - * @author Alexander Nozik. + * @author Alexander Nozik */ public inline fun MstExpression>.compile(): Expression = mst.compileWith(T::class.java, algebra) diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt index 9a38ce81a..8ecb0adda 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt @@ -21,7 +21,8 @@ import space.kscience.kmath.operations.RingOperations /** * better-parse implementation of grammar defined in the ArithmeticsEvaluator.g4. * - * @author Alexander Nozik and Iaroslav Postovalov + * @author Alexander Nozik + * @author Iaroslav Postovalov */ public object ArithmeticsEvaluator : Grammar() { // TODO replace with "...".toRegex() when better-parse 0.4.1 is released diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt new file mode 100644 index 000000000..b10f7ed4e --- /dev/null +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt @@ -0,0 +1,90 @@ +package space.kscience.kmath.ast.rendering + +import space.kscience.kmath.ast.MST.Numeric +import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import kotlin.test.Test + +internal class TestFeatures { + @Test + fun printSymbolic() = testLatex("x", "x") + + @Test + fun printNumeric() { + val num = object : Number() { + override fun toByte(): Byte = throw UnsupportedOperationException() + override fun toChar(): Char = throw UnsupportedOperationException() + override fun toDouble(): Double = throw UnsupportedOperationException() + override fun toFloat(): Float = throw UnsupportedOperationException() + override fun toInt(): Int = throw UnsupportedOperationException() + override fun toLong(): Long = throw UnsupportedOperationException() + override fun toShort(): Short = throw UnsupportedOperationException() + override fun toString(): String = "foo" + } + + testLatex(Numeric(num), "foo") + } + + @Test + fun prettyPrintFloats() { + testLatex(Numeric(Double.NaN), "NaN") + testLatex(Numeric(Double.POSITIVE_INFINITY), "\\infty") + testLatex(Numeric(Double.NEGATIVE_INFINITY), "-\\infty") + testLatex(Numeric(1.0), "1") + testLatex(Numeric(-1.0), "-1") + testLatex(Numeric(1.42), "1.42") + testLatex(Numeric(-1.42), "-1.42") + testLatex(Numeric(1.1e10), "1.1\\times10^{10}") + testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}") + testLatex(Numeric(-1.1e-10), "-1.1\\times10^{-10}") + testLatex(Numeric(-1.1e10), "-1.1\\times10^{10}") + } + + @Test + fun prettyPrintIntegers() { + testLatex(Numeric(42), "42") + testLatex(Numeric(-42), "-42") + } + + @Test + fun binaryPlus() = testLatex("2+2", "2+2") + + @Test + fun binaryMinus() = testLatex("2-2", "2-2") + + @Test + fun fraction() = testLatex("2/2", "\\frac{2}{2}") + + @Test + fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)") + + @Test + fun unaryOperator() = testLatex("f(x)", "\\operatorname{f}\\,\\left(x\\right)") + + @Test + fun power() = testLatex("x^y", "x^{y}") + + @Test + fun squareRoot() = testLatex("sqrt(x)", "\\sqrt{x}") + + @Test + fun exponential() = testLatex("exp(x)", "e^{x}") + + @Test + fun multiplication() = testLatex("x*1", "x\\times1") + + @Test + fun inverseTrigonometry() { + testLatex("asin(x)", "\\operatorname{sin}^{-1}\\,\\left(x\\right)") + testLatex("asinh(x)", "\\operatorname{sinh}^{-1}\\,\\left(x\\right)") + testLatex("acos(x)", "\\operatorname{cos}^{-1}\\,\\left(x\\right)") + testLatex("acosh(x)", "\\operatorname{cosh}^{-1}\\,\\left(x\\right)") + testLatex("atan(x)", "\\operatorname{tan}^{-1}\\,\\left(x\\right)") + testLatex("atanh(x)", "\\operatorname{tanh}^{-1}\\,\\left(x\\right)") + } + +// @Test +// fun unaryPlus() { +// testLatex("+1", "+1") +// testLatex("+1", "++1") +// } +} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt new file mode 100644 index 000000000..9c1009042 --- /dev/null +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt @@ -0,0 +1,65 @@ +package space.kscience.kmath.ast.rendering + +import space.kscience.kmath.ast.MST +import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import space.kscience.kmath.operations.GroupOperations +import kotlin.test.Test + +internal class TestLatex { + @Test + fun number() = testLatex("42", "42") + + @Test + fun symbol() = testLatex("x", "x") + + @Test + fun operatorName() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") + + @Test + fun specialSymbol() = testLatex(MST.Numeric(Double.POSITIVE_INFINITY), "\\infty") + + @Test + fun operand() { + testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") + testLatex("1+1", "1+1") + } + + @Test + fun unaryOperator() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") + + @Test + fun unaryPlus() = testLatex(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1") + + @Test + fun unaryMinus() = testLatex("-x", "-x") + + @Test + fun radical() = testLatex("sqrt(x)", "\\sqrt{x}") + + @Test + fun superscript() = testLatex("x^y", "x^{y}") + + @Test + fun subscript() = testLatex(SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), "x_{123}") + + @Test + fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)") + + @Test + fun binaryPlus() = testLatex("x+x", "x+x") + + @Test + fun binaryMinus() = testLatex("x-x", "x-x") + + @Test + fun fraction() = testLatex("x/x", "\\frac{x}{x}") + + @Test + fun radicalWithIndex() = testLatex(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), "\\sqrt[x]{y}") + + @Test + fun multiplication() { + testLatex("x*1", "x\\times1") + testLatex("1*x", "1\\,x") + } +} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt new file mode 100644 index 000000000..c9a462840 --- /dev/null +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt @@ -0,0 +1,84 @@ +package space.kscience.kmath.ast.rendering + +import space.kscience.kmath.ast.MST +import space.kscience.kmath.ast.rendering.TestUtils.testMathML +import space.kscience.kmath.operations.GroupOperations +import kotlin.test.Test + +internal class TestMathML { + @Test + fun number() = testMathML("42", "42") + + @Test + fun symbol() = testMathML("x", "x") + + @Test + fun operatorName() = testMathML( + "sin(1)", + "sin1", + ) + + @Test + fun specialSymbol() = testMathML(MST.Numeric(Double.POSITIVE_INFINITY), "") + + @Test + fun operand() { + testMathML( + "sin(1)", + "sin1", + ) + + testMathML("1+1", "1+1") + } + + @Test + fun unaryOperator() = testMathML( + "sin(1)", + "sin1", + ) + + @Test + fun unaryPlus() = + testMathML(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1") + + @Test + fun unaryMinus() = testMathML("-x", "-x") + + @Test + fun radical() = testMathML("sqrt(x)", "x") + + @Test + fun superscript() = testMathML("x^y", "xy") + + @Test + fun subscript() = testMathML( + SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), + "x123", + ) + + @Test + fun binaryOperator() = testMathML( + "f(x, y)", + "fx,y", + ) + + @Test + fun binaryPlus() = testMathML("x+x", "x+x") + + @Test + fun binaryMinus() = testMathML("x-x", "x-x") + + @Test + fun fraction() = testMathML("x/x", "xx") + + @Test + fun radicalWithIndex() = + testMathML(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), + "yx") + + @Test + fun multiplication() { + testMathML("x*1", "x×1") + testMathML("1*x", "1x") + } +} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt new file mode 100644 index 000000000..56a799c2c --- /dev/null +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt @@ -0,0 +1,28 @@ +package space.kscience.kmath.ast.rendering + +import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import kotlin.test.Test + +internal class TestStages { + @Test + fun betterMultiplication() { + testLatex("a*1", "a\\times1") + testLatex("1*(2/3)", "1\\times\\left(\\frac{2}{3}\\right)") + testLatex("1*1", "1\\times1") + testLatex("2e10", "2\\times10^{10}") + testLatex("2*x", "2\\,x") + testLatex("2*(x+1)", "2\\,\\left(x+1\\right)") + testLatex("x*y", "x\\,y") + } + + @Test + fun parentheses() { + testLatex("(x+1)", "x+1") + testLatex("x*x*x", "x\\,x\\,x") + testLatex("(x+x)*x", "\\left(x+x\\right)\\,x") + testLatex("x+x*x", "x+x\\,x") + testLatex("x+x^x*x+x", "x+x^{x}\\,x+x") + testLatex("(x+x)^x+x*x", "\\left(x+x\\right)^{x}+x\\,x") + testLatex("x^(x+x)", "x^{x+x}") + } +} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt new file mode 100644 index 000000000..e6359bcc9 --- /dev/null +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt @@ -0,0 +1,41 @@ +package space.kscience.kmath.ast.rendering + +import space.kscience.kmath.ast.MST +import space.kscience.kmath.ast.parseMath +import kotlin.test.assertEquals + +internal object TestUtils { + private fun mathSyntax(mst: MST) = FeaturedMathRendererWithPostProcess.Default.render(mst) + private fun latex(mst: MST) = LatexSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst)) + private fun mathML(mst: MST) = MathMLSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst)) + + internal fun testLatex(mst: MST, expectedLatex: String) = assertEquals( + expected = expectedLatex, + actual = latex(mst), + ) + + internal fun testLatex(expression: String, expectedLatex: String) = assertEquals( + expected = expectedLatex, + actual = latex(expression.parseMath()), + ) + + internal fun testLatex(expression: MathSyntax, expectedLatex: String) = assertEquals( + expected = expectedLatex, + actual = LatexSyntaxRenderer.renderWithStringBuilder(expression), + ) + + internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals( + expected = "$expectedMathML", + actual = mathML(mst), + ) + + internal fun testMathML(expression: String, expectedMathML: String) = assertEquals( + expected = "$expectedMathML", + actual = mathML(expression.parseMath()), + ) + + internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals( + expected = "$expectedMathML", + actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression), + ) +} diff --git a/kmath-complex/README.md b/kmath-complex/README.md index d7b2937fd..ec5bf289f 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-3`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-4`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0-dev-3' + implementation 'space.kscience:kmath-complex:0.3.0-dev-4' } ``` **Gradle Kotlin DSL:** @@ -31,6 +31,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0-dev-3") + implementation("space.kscience:kmath-complex:0.3.0-dev-4") } ``` diff --git a/kmath-core/README.md b/kmath-core/README.md index 096c7d833..5e4f1765d 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-3`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-4`. **Gradle:** ```gradle @@ -26,7 +26,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0-dev-3' + implementation 'space.kscience:kmath-core:0.3.0-dev-4' } ``` **Gradle Kotlin DSL:** @@ -38,6 +38,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0-dev-3") + implementation("space.kscience:kmath-core:0.3.0-dev-4") } ``` diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 18fbf0fdd..817bc9f9c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -18,7 +18,8 @@ private typealias TBase = ULong /** * Kotlin Multiplatform implementation of Big Integer numbers (KBigInteger). * - * @author Robert Drynkin (https://github.com/robdrynkin) and Peter Klimai (https://github.com/pklimai) + * @author Robert Drynkin + * @author Peter Klimai */ @OptIn(UnstableKMathAPI::class) public object BigIntField : Field, NumbersAddOperations, ScaleOperations { diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index 2551703a4..1f13a03c5 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-3`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-4`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0-dev-3' + implementation 'space.kscience:kmath-ejml:0.3.0-dev-4' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0-dev-3") + implementation("space.kscience:kmath-ejml:0.3.0-dev-4") } ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index ad3d33062..f9c6ed3a0 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-3`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-4`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0-dev-3' + implementation 'space.kscience:kmath-for-real:0.3.0-dev-4' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0-dev-3") + implementation("space.kscience:kmath-for-real:0.3.0-dev-4") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 531e97a44..1e4b06e0f 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -10,7 +10,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-3`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-4`. **Gradle:** ```gradle @@ -21,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0-dev-3' + implementation 'space.kscience:kmath-functions:0.3.0-dev-4' } ``` **Gradle Kotlin DSL:** @@ -33,6 +33,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0-dev-3") + implementation("space.kscience:kmath-functions:0.3.0-dev-4") } ``` diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 938d05c33..c8944f1ab 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-3`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-4`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0-dev-3' + implementation 'space.kscience:kmath-nd4j:0.3.0-dev-4' } ``` **Gradle Kotlin DSL:** @@ -32,7 +32,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0-dev-3") + implementation("space.kscience:kmath-nd4j:0.3.0-dev-4") } ``` From c2bab5d13857ac9d6a5a00f9667d1e21ce8bee95 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 1 Apr 2021 18:18:54 +0300 Subject: [PATCH 162/393] Fix Samplers and distribution API --- .../kmath/commons/fit/fitWithAutoDiff.kt | 2 +- .../kmath/stat/DistributionBenchmark.kt | 6 +- .../kscience/kmath/stat/DistributionDemo.kt | 2 +- .../commons/optimization/OptimizeTest.kt | 2 +- .../kscience/kmath/chains/BlockingChain.kt | 50 ++++ .../kmath/chains/BlockingDoubleChain.kt | 22 +- .../kscience/kmath/chains/BlockingIntChain.kt | 11 +- .../space/kscience/kmath/chains/Chain.kt | 28 +-- .../kscience/kmath/streaming/BufferFlow.kt | 3 +- kmath-stat/build.gradle.kts | 4 + .../kmath/distributions/Distribution.kt | 38 +++ .../FactorizedDistribution.kt | 3 +- .../distributions/NormalDistribution.kt | 15 +- .../kmath/{stat => }/internal/InternalErf.kt | 2 +- .../{stat => }/internal/InternalGamma.kt | 2 +- .../{stat => }/internal/InternalUtils.kt | 2 +- .../AhrensDieterExponentialSampler.kt | 72 ++++++ .../AhrensDieterMarsagliaTsangGammaSampler.kt | 4 +- .../samplers/AliasMethodDiscreteSampler.kt | 220 +++++++++--------- .../kmath/samplers/BoxMullerSampler.kt | 52 +++++ .../kmath/samplers/ConstantSampler.kt | 13 ++ .../kmath/samplers/GaussianSampler.kt | 34 +++ .../samplers/KempSmallMeanPoissonSampler.kt | 68 ++++++ .../MarsagliaNormalizedGaussianSampler.kt | 61 +++++ .../samplers/NormalizedGaussianSampler.kt | 18 ++ .../kscience/kmath/samplers/PoissonSampler.kt | 203 ++++++++++++++++ .../ZigguratNormalizedGaussianSampler.kt | 88 +++++++ .../space/kscience/kmath/stat/RandomChain.kt | 24 +- .../kscience/kmath/stat/RandomGenerator.kt | 6 + .../stat/{Distribution.kt => Sampler.kt} | 46 +--- .../space/kscience/kmath/stat/Statistic.kt | 2 +- .../kmath/stat/UniformDistribution.kt | 2 + .../AhrensDieterExponentialSampler.kt | 73 ------ .../BoxMullerNormalizedGaussianSampler.kt | 48 ---- .../kmath/stat/samplers/GaussianSampler.kt | 43 ---- .../samplers/KempSmallMeanPoissonSampler.kt | 63 ----- .../stat/samplers/LargeMeanPoissonSampler.kt | 130 ----------- .../MarsagliaNormalizedGaussianSampler.kt | 61 ----- .../samplers/NormalizedGaussianSampler.kt | 9 - .../kmath/stat/samplers/PoissonSampler.kt | 30 --- .../stat/samplers/SmallMeanPoissonSampler.kt | 50 ---- .../ZigguratNormalizedGaussianSampler.kt | 88 ------- .../kmath/stat/CommonsDistributionsTest.kt | 19 +- .../kscience/kmath/stat/StatisticTest.kt | 2 +- 44 files changed, 915 insertions(+), 806 deletions(-) create mode 100644 kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingChain.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/Distribution.kt rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => distributions}/FactorizedDistribution.kt (94%) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => }/distributions/NormalDistribution.kt (71%) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => }/internal/InternalErf.kt (90%) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => }/internal/InternalGamma.kt (99%) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => }/internal/InternalUtils.kt (98%) create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => }/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt (97%) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{stat => }/samplers/AliasMethodDiscreteSampler.kt (58%) create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ConstantSampler.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/{Distribution.kt => Sampler.kt} (54%) delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/GaussianSampler.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/PoissonSampler.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt index 04c55b34c..02534ac98 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -7,6 +7,7 @@ import kscience.plotly.models.ScatterMode import kscience.plotly.models.TraceValues import space.kscience.kmath.commons.optimization.chiSquared import space.kscience.kmath.commons.optimization.minimize +import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.misc.symbol import space.kscience.kmath.optimization.FunctionOptimization import space.kscience.kmath.optimization.OptimizationResult @@ -14,7 +15,6 @@ import space.kscience.kmath.real.DoubleVector import space.kscience.kmath.real.map import space.kscience.kmath.real.step import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.distributions.NormalDistribution import space.kscience.kmath.structures.asIterable import space.kscience.kmath.structures.toList import kotlin.math.pow diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt index bfd138502..5cf96adaa 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt @@ -3,8 +3,8 @@ package space.kscience.kmath.stat import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking -import space.kscience.kmath.stat.samplers.GaussianSampler import org.apache.commons.rng.simple.RandomSource +import space.kscience.kmath.samplers.GaussianSampler import java.time.Duration import java.time.Instant import org.apache.commons.rng.sampling.distribution.GaussianSampler as CMGaussianSampler @@ -12,8 +12,8 @@ import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSa private suspend fun runKMathChained(): Duration { val generator = RandomGenerator.fromSource(RandomSource.MT, 123L) - val normal = GaussianSampler.of(7.0, 2.0) - val chain = normal.sample(generator).blocking() + val normal = GaussianSampler(7.0, 2.0) + val chain = normal.sample(generator) val startTime = Instant.now() var sum = 0.0 diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt index aac7d51d4..1e8542bd8 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt @@ -3,7 +3,7 @@ package space.kscience.kmath.stat import kotlinx.coroutines.runBlocking import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.collectWithState -import space.kscience.kmath.stat.distributions.NormalDistribution +import space.kscience.kmath.distributions.NormalDistribution /** * The state of distribution averager. diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt index 36f2639f4..a51c407c2 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -2,10 +2,10 @@ package space.kscience.kmath.commons.optimization import kotlinx.coroutines.runBlocking import space.kscience.kmath.commons.expressions.DerivativeStructureExpression +import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.misc.symbol import space.kscience.kmath.optimization.FunctionOptimization import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.distributions.NormalDistribution import kotlin.math.pow import kotlin.test.Test diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingChain.kt new file mode 100644 index 000000000..429175126 --- /dev/null +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingChain.kt @@ -0,0 +1,50 @@ +package space.kscience.kmath.chains + +import space.kscience.kmath.structures.Buffer + + +public interface BufferChain : Chain { + public suspend fun nextBuffer(size: Int): Buffer + override suspend fun fork(): BufferChain +} + +/** + * A chain with blocking generator that could be used without suspension + */ +public interface BlockingChain : Chain { + /** + * Get the next value without concurrency support. Not guaranteed to be thread safe. + */ + public fun nextBlocking(): T + + override suspend fun next(): T = nextBlocking() + + override suspend fun fork(): BlockingChain +} + + +public interface BlockingBufferChain : BlockingChain, BufferChain { + + public fun nextBufferBlocking(size: Int): Buffer + + public override fun nextBlocking(): T = nextBufferBlocking(1)[0] + + public override suspend fun nextBuffer(size: Int): Buffer = nextBufferBlocking(size) + + override suspend fun fork(): BlockingBufferChain +} + + +public suspend inline fun Chain.nextBuffer(size: Int): Buffer = if (this is BufferChain) { + nextBuffer(size) +} else { + Buffer.auto(size) { next() } +} + +public inline fun BlockingChain.nextBufferBlocking( + size: Int, +): Buffer = if (this is BlockingBufferChain) { + nextBufferBlocking(size) +} else { + Buffer.auto(size) { nextBlocking() } +} \ No newline at end of file diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt index d024147b4..c2153ff6a 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt @@ -1,13 +1,27 @@ package space.kscience.kmath.chains +import space.kscience.kmath.structures.DoubleBuffer + /** - * Chunked, specialized chain for real values. + * Chunked, specialized chain for double values, which supports blocking [nextBlocking] operation */ -public interface BlockingDoubleChain : Chain { - public override suspend fun next(): Double +public interface BlockingDoubleChain : BlockingBufferChain { /** * Returns an [DoubleArray] chunk of [size] values of [next]. */ - public suspend fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { next() } + public override fun nextBufferBlocking(size: Int): DoubleBuffer + + override suspend fun fork(): BlockingDoubleChain + + public companion object } + +public fun BlockingDoubleChain.map(transform: (Double) -> Double): BlockingDoubleChain = object : BlockingDoubleChain { + override fun nextBufferBlocking(size: Int): DoubleBuffer { + val block = this@map.nextBufferBlocking(size) + return DoubleBuffer(size) { transform(block[it]) } + } + + override suspend fun fork(): BlockingDoubleChain = this@map.fork().map(transform) +} \ No newline at end of file diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt index fb2e453ad..21a498646 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt @@ -1,9 +1,12 @@ package space.kscience.kmath.chains +import space.kscience.kmath.structures.IntBuffer + /** * Performance optimized chain for integer values */ -public interface BlockingIntChain : Chain { - public override suspend fun next(): Int - public suspend fun nextBlock(size: Int): IntArray = IntArray(size) { next() } -} +public interface BlockingIntChain : BlockingBufferChain { + override fun nextBufferBlocking(size: Int): IntBuffer + + override suspend fun fork(): BlockingIntChain +} \ No newline at end of file diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt index a961f2e09..adeaea5a7 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt @@ -24,20 +24,20 @@ import kotlinx.coroutines.sync.withLock /** * A not-necessary-Markov chain of some type - * @param R - the chain element type + * @param T - the chain element type */ -public interface Chain : Flow { +public interface Chain : Flow { /** * Generate next value, changing state if needed */ - public suspend fun next(): R + public suspend fun next(): T /** * Create a copy of current chain state. Consuming resulting chain does not affect initial chain */ - public fun fork(): Chain + public suspend fun fork(): Chain - override suspend fun collect(collector: FlowCollector): Unit = + override suspend fun collect(collector: FlowCollector): Unit = flow { while (true) emit(next()) }.collect(collector) public companion object @@ -51,7 +51,7 @@ public fun Sequence.asChain(): Chain = iterator().asChain() */ public class SimpleChain(private val gen: suspend () -> R) : Chain { public override suspend fun next(): R = gen() - public override fun fork(): Chain = this + public override suspend fun fork(): Chain = this } /** @@ -69,7 +69,7 @@ public class MarkovChain(private val seed: suspend () -> R, private newValue } - public override fun fork(): Chain = MarkovChain(seed = { value ?: seed() }, gen = gen) + public override suspend fun fork(): Chain = MarkovChain(seed = { value ?: seed() }, gen = gen) } /** @@ -94,7 +94,7 @@ public class StatefulChain( newValue } - public override fun fork(): Chain = StatefulChain(forkState(state), seed, forkState, gen) + public override suspend fun fork(): Chain = StatefulChain(forkState(state), seed, forkState, gen) } /** @@ -102,7 +102,7 @@ public class StatefulChain( */ public class ConstantChain(public val value: T) : Chain { public override suspend fun next(): T = value - public override fun fork(): Chain = this + public override suspend fun fork(): Chain = this } /** @@ -111,7 +111,7 @@ public class ConstantChain(public val value: T) : Chain { */ public fun Chain.map(func: suspend (T) -> R): Chain = object : Chain { override suspend fun next(): R = func(this@map.next()) - override fun fork(): Chain = this@map.fork().map(func) + override suspend fun fork(): Chain = this@map.fork().map(func) } /** @@ -127,7 +127,7 @@ public fun Chain.filter(block: (T) -> Boolean): Chain = object : Chain return next } - override fun fork(): Chain = this@filter.fork().filter(block) + override suspend fun fork(): Chain = this@filter.fork().filter(block) } /** @@ -135,7 +135,7 @@ public fun Chain.filter(block: (T) -> Boolean): Chain = object : Chain */ public fun Chain.collect(mapper: suspend (Chain) -> R): Chain = object : Chain { override suspend fun next(): R = mapper(this@collect) - override fun fork(): Chain = this@collect.fork().collect(mapper) + override suspend fun fork(): Chain = this@collect.fork().collect(mapper) } public fun Chain.collectWithState( @@ -145,7 +145,7 @@ public fun Chain.collectWithState( ): Chain = object : Chain { override suspend fun next(): R = state.mapper(this@collectWithState) - override fun fork(): Chain = + override suspend fun fork(): Chain = this@collectWithState.fork().collectWithState(stateFork(state), stateFork, mapper) } @@ -154,5 +154,5 @@ public fun Chain.collectWithState( */ public fun Chain.zip(other: Chain, block: suspend (T, U) -> R): Chain = object : Chain { override suspend fun next(): R = block(this@zip.next(), other.next()) - override fun fork(): Chain = this@zip.fork().zip(other.fork(), block) + override suspend fun fork(): Chain = this@zip.fork().zip(other.fork(), block) } diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt index dc1dd4757..655f94cdf 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt @@ -6,7 +6,6 @@ import space.kscience.kmath.chains.BlockingDoubleChain import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.DoubleBuffer -import space.kscience.kmath.structures.asBuffer /** * Create a [Flow] from buffer @@ -50,7 +49,7 @@ public fun Flow.chunked(bufferSize: Int): Flow = flow { if (this@chunked is BlockingDoubleChain) { // performance optimization for blocking primitive chain - while (true) emit(nextBlock(bufferSize).asBuffer()) + while (true) emit(nextBufferBlocking(bufferSize)) } else { val array = DoubleArray(bufferSize) var counter = 0 diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index bc3890b1e..c2ebb7ea1 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -2,6 +2,10 @@ plugins { id("ru.mipt.npm.gradle.mpp") } +kscience{ + useAtomic() +} + kotlin.sourceSets { commonMain { dependencies { diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/Distribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/Distribution.kt new file mode 100644 index 000000000..fcad8ef99 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/Distribution.kt @@ -0,0 +1,38 @@ +package space.kscience.kmath.distributions + +import space.kscience.kmath.chains.Chain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler + +/** + * A distribution of typed objects. + */ +public interface Distribution : Sampler { + /** + * A probability value for given argument [arg]. + * For continuous distributions returns PDF + */ + public fun probability(arg: T): Double + + public override fun sample(generator: RandomGenerator): Chain + + /** + * An empty companion. Distribution factories should be written as its extensions + */ + public companion object +} + +public interface UnivariateDistribution> : Distribution { + /** + * Cumulative distribution for ordered parameter (CDF) + */ + public fun cumulative(arg: T): Double +} + +/** + * Compute probability integral in an interval + */ +public fun > UnivariateDistribution.integral(from: T, to: T): Double { + require(to > from) + return cumulative(to) - cumulative(from) +} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/FactorizedDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/FactorizedDistribution.kt similarity index 94% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/FactorizedDistribution.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/FactorizedDistribution.kt index 3dd506b67..e69086af4 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/FactorizedDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/FactorizedDistribution.kt @@ -1,7 +1,8 @@ -package space.kscience.kmath.stat +package space.kscience.kmath.distributions import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.SimpleChain +import space.kscience.kmath.stat.RandomGenerator /** * A multivariate distribution which takes a map of parameters diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/distributions/NormalDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt similarity index 71% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/distributions/NormalDistribution.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt index 6515cbaa7..15593aed5 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/distributions/NormalDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt @@ -1,12 +1,11 @@ -package space.kscience.kmath.stat.distributions +package space.kscience.kmath.distributions import space.kscience.kmath.chains.Chain +import space.kscience.kmath.internal.InternalErf +import space.kscience.kmath.samplers.GaussianSampler +import space.kscience.kmath.samplers.NormalizedGaussianSampler +import space.kscience.kmath.samplers.ZigguratNormalizedGaussianSampler import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.UnivariateDistribution -import space.kscience.kmath.stat.internal.InternalErf -import space.kscience.kmath.stat.samplers.GaussianSampler -import space.kscience.kmath.stat.samplers.NormalizedGaussianSampler -import space.kscience.kmath.stat.samplers.ZigguratNormalizedGaussianSampler import kotlin.math.* /** @@ -16,8 +15,8 @@ public inline class NormalDistribution(public val sampler: GaussianSampler) : Un public constructor( mean: Double, standardDeviation: Double, - normalized: NormalizedGaussianSampler = ZigguratNormalizedGaussianSampler.of(), - ) : this(GaussianSampler.of(mean, standardDeviation, normalized)) + normalized: NormalizedGaussianSampler = ZigguratNormalizedGaussianSampler, + ) : this(GaussianSampler(mean, standardDeviation, normalized)) public override fun probability(arg: Double): Double { val x1 = (arg - sampler.mean) / sampler.standardDeviation diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalErf.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt similarity index 90% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalErf.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt index 4e1623867..3b9110c1a 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalErf.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt @@ -1,4 +1,4 @@ -package space.kscience.kmath.stat.internal +package space.kscience.kmath.internal import kotlin.math.abs diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalGamma.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt similarity index 99% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalGamma.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt index 4f5adbe97..96f5c66db 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalGamma.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt @@ -1,4 +1,4 @@ -package space.kscience.kmath.stat.internal +package space.kscience.kmath.internal import kotlin.math.* diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalUtils.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt similarity index 98% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalUtils.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt index 722eee946..832689b27 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/internal/InternalUtils.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt @@ -1,4 +1,4 @@ -package space.kscience.kmath.stat.internal +package space.kscience.kmath.internal import kotlin.math.ln import kotlin.math.min diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt new file mode 100644 index 000000000..0b8ecfb31 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt @@ -0,0 +1,72 @@ +package space.kscience.kmath.samplers + +import space.kscience.kmath.chains.BlockingDoubleChain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.structures.DoubleBuffer +import kotlin.math.ln +import kotlin.math.pow + +/** + * Sampling from an [exponential distribution](http://mathworld.wolfram.com/ExponentialDistribution.html). + * + * Based on Commons RNG implementation. + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.html]. + */ +public class AhrensDieterExponentialSampler(public val mean: Double) : Sampler { + + init { + require(mean > 0) { "mean is not strictly positive: $mean" } + } + + public override fun sample(generator: RandomGenerator): BlockingDoubleChain = object : BlockingDoubleChain { + override fun nextBlocking(): Double { + // Step 1: + var a = 0.0 + var u = generator.nextDouble() + + // Step 2 and 3: + while (u < 0.5) { + a += EXPONENTIAL_SA_QI[0] + u *= 2.0 + } + + // Step 4 (now u >= 0.5): + u += u - 1 + // Step 5: + if (u <= EXPONENTIAL_SA_QI[0]) return mean * (a + u) + // Step 6: + var i = 0 // Should be 1, be we iterate before it in while using 0. + var u2 = generator.nextDouble() + var umin = u2 + + // Step 7 and 8: + do { + ++i + u2 = generator.nextDouble() + if (u2 < umin) umin = u2 + // Step 8: + } while (u > EXPONENTIAL_SA_QI[i]) // Ensured to exit since EXPONENTIAL_SA_QI[MAX] = 1. + + return mean * (a + umin * EXPONENTIAL_SA_QI[0]) + } + + override fun nextBufferBlocking(size: Int): DoubleBuffer = DoubleBuffer(size) { nextBlocking() } + + override suspend fun fork(): BlockingDoubleChain = sample(generator.fork()) + } + + public companion object { + private val EXPONENTIAL_SA_QI by lazy { + val ln2 = ln(2.0) + var qi = 0.0 + + DoubleArray(16) { i -> + qi += ln2.pow(i + 1.0) / space.kscience.kmath.internal.InternalUtils.factorial(i + 1) + qi + } + } + } + +} + diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt similarity index 97% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt index 81182f6cd..c8a49106b 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt @@ -1,4 +1,4 @@ -package space.kscience.kmath.stat.samplers +package space.kscience.kmath.samplers import space.kscience.kmath.chains.Chain import space.kscience.kmath.stat.RandomGenerator @@ -80,7 +80,7 @@ public class AhrensDieterMarsagliaTsangGammaSampler private constructor( private val gaussian: NormalizedGaussianSampler init { - gaussian = ZigguratNormalizedGaussianSampler.of() + gaussian = ZigguratNormalizedGaussianSampler dOptim = alpha - ONE_THIRD cOptim = ONE_THIRD / sqrt(dOptim) } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt similarity index 58% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt index cae97db65..fe670a4e4 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AliasMethodDiscreteSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt @@ -1,10 +1,10 @@ -package space.kscience.kmath.stat.samplers +package space.kscience.kmath.samplers import space.kscience.kmath.chains.Chain +import space.kscience.kmath.internal.InternalUtils import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.stat.Sampler import space.kscience.kmath.stat.chain -import space.kscience.kmath.stat.internal.InternalUtils import kotlin.math.ceil import kotlin.math.max import kotlin.math.min @@ -39,12 +39,12 @@ import kotlin.math.min public open class AliasMethodDiscreteSampler private constructor( // Deliberate direct storage of input arrays protected val probability: LongArray, - protected val alias: IntArray + protected val alias: IntArray, ) : Sampler { private class SmallTableAliasMethodDiscreteSampler( probability: LongArray, - alias: IntArray + alias: IntArray, ) : AliasMethodDiscreteSampler(probability, alias) { // Assume the table size is a power of 2 and create the mask private val mask: Int = alias.size - 1 @@ -111,110 +111,6 @@ public open class AliasMethodDiscreteSampler private constructor( private const val CONVERT_TO_NUMERATOR: Double = ONE_AS_NUMERATOR.toDouble() private const val MAX_SMALL_POWER_2_SIZE = 1 shl 11 - public fun of( - probabilities: DoubleArray, - alpha: Int = DEFAULT_ALPHA - ): Sampler { - // The Alias method balances N categories with counts around the mean into N sections, - // each allocated 'mean' observations. - // - // Consider 4 categories with counts 6,3,2,1. The histogram can be balanced into a - // 2D array as 4 sections with a height of the mean: - // - // 6 - // 6 - // 6 - // 63 => 6366 -- - // 632 6326 |-- mean - // 6321 6321 -- - // - // section abcd - // - // Each section is divided as: - // a: 6=1/1 - // b: 3=1/1 - // c: 2=2/3; 6=1/3 (6 is the alias) - // d: 1=1/3; 6=2/3 (6 is the alias) - // - // The sample is obtained by randomly selecting a section, then choosing which category - // from the pair based on a uniform random deviate. - val sumProb = InternalUtils.validateProbabilities(probabilities) - // Allow zero-padding - val n = computeSize(probabilities.size, alpha) - // Partition into small and large by splitting on the average. - val mean = sumProb / n - // The cardinality of smallSize + largeSize = n. - // So fill the same array from either end. - val indices = IntArray(n) - var large = n - var small = 0 - - probabilities.indices.forEach { i -> - if (probabilities[i] >= mean) indices[--large] = i else indices[small++] = i - } - - small = fillRemainingIndices(probabilities.size, indices, small) - // This may be smaller than the input length if the probabilities were already padded. - val nonZeroIndex = findLastNonZeroIndex(probabilities) - // The probabilities are modified so use a copy. - // Note: probabilities are required only up to last nonZeroIndex - val remainingProbabilities = probabilities.copyOf(nonZeroIndex + 1) - // Allocate the final tables. - // Probability table may be truncated (when zero padded). - // The alias table is full length. - val probability = LongArray(remainingProbabilities.size) - val alias = IntArray(n) - - // This loop uses each large in turn to fill the alias table for small probabilities that - // do not reach the requirement to fill an entire section alone (i.e. p < mean). - // Since the sum of the small should be less than the sum of the large it should use up - // all the small first. However floating point round-off can result in - // misclassification of items as small or large. The Vose algorithm handles this using - // a while loop conditioned on the size of both sets and a subsequent loop to use - // unpaired items. - while (large != n && small != 0) { - // Index of the small and the large probabilities. - val j = indices[--small] - val k = indices[large++] - - // Optimisation for zero-padded input: - // p(j) = 0 above the last nonZeroIndex - if (j > nonZeroIndex) - // The entire amount for the section is taken from the alias. - remainingProbabilities[k] -= mean - else { - val pj = remainingProbabilities[j] - // Item j is a small probability that is below the mean. - // Compute the weight of the section for item j: pj / mean. - // This is scaled by 2^53 and the ceiling function used to round-up - // the probability to a numerator of a fraction in the range [1,2^53]. - // Ceiling ensures non-zero values. - probability[j] = ceil(CONVERT_TO_NUMERATOR * (pj / mean)).toLong() - // The remaining amount for the section is taken from the alias. - // Effectively: probabilities[k] -= (mean - pj) - remainingProbabilities[k] += pj - mean - } - - // If not j then the alias is k - alias[j] = k - - // Add the remaining probability from large to the appropriate list. - if (remainingProbabilities[k] >= mean) indices[--large] = k else indices[small++] = k - } - - // Final loop conditions to consume unpaired items. - // Note: The large set should never be non-empty but this can occur due to round-off - // error so consume from both. - fillTable(probability, alias, indices, 0, small) - fillTable(probability, alias, indices, large, n) - - // Change the algorithm for small power of 2 sized tables - return if (isSmallPowerOf2(n)) - SmallTableAliasMethodDiscreteSampler(probability, alias) - else - AliasMethodDiscreteSampler(probability, alias) - } - private fun fillRemainingIndices(length: Int, indices: IntArray, small: Int): Int { var updatedSmall = small (length until indices.size).forEach { i -> indices[updatedSmall++] = i } @@ -246,7 +142,7 @@ public open class AliasMethodDiscreteSampler private constructor( alias: IntArray, indices: IntArray, start: Int, - end: Int + end: Int, ) = (start until end).forEach { i -> val index = indices[i] probability[index] = ONE_AS_NUMERATOR @@ -283,4 +179,110 @@ public open class AliasMethodDiscreteSampler private constructor( return n - (mutI ushr 1) } } + + @Suppress("FunctionName") + public fun AliasMethodDiscreteSampler( + probabilities: DoubleArray, + alpha: Int = DEFAULT_ALPHA, + ): Sampler { + // The Alias method balances N categories with counts around the mean into N sections, + // each allocated 'mean' observations. + // + // Consider 4 categories with counts 6,3,2,1. The histogram can be balanced into a + // 2D array as 4 sections with a height of the mean: + // + // 6 + // 6 + // 6 + // 63 => 6366 -- + // 632 6326 |-- mean + // 6321 6321 -- + // + // section abcd + // + // Each section is divided as: + // a: 6=1/1 + // b: 3=1/1 + // c: 2=2/3; 6=1/3 (6 is the alias) + // d: 1=1/3; 6=2/3 (6 is the alias) + // + // The sample is obtained by randomly selecting a section, then choosing which category + // from the pair based on a uniform random deviate. + val sumProb = InternalUtils.validateProbabilities(probabilities) + // Allow zero-padding + val n = computeSize(probabilities.size, alpha) + // Partition into small and large by splitting on the average. + val mean = sumProb / n + // The cardinality of smallSize + largeSize = n. + // So fill the same array from either end. + val indices = IntArray(n) + var large = n + var small = 0 + + probabilities.indices.forEach { i -> + if (probabilities[i] >= mean) indices[--large] = i else indices[small++] = i + } + + small = fillRemainingIndices(probabilities.size, indices, small) + // This may be smaller than the input length if the probabilities were already padded. + val nonZeroIndex = findLastNonZeroIndex(probabilities) + // The probabilities are modified so use a copy. + // Note: probabilities are required only up to last nonZeroIndex + val remainingProbabilities = probabilities.copyOf(nonZeroIndex + 1) + // Allocate the final tables. + // Probability table may be truncated (when zero padded). + // The alias table is full length. + val probability = LongArray(remainingProbabilities.size) + val alias = IntArray(n) + + // This loop uses each large in turn to fill the alias table for small probabilities that + // do not reach the requirement to fill an entire section alone (i.e. p < mean). + // Since the sum of the small should be less than the sum of the large it should use up + // all the small first. However floating point round-off can result in + // misclassification of items as small or large. The Vose algorithm handles this using + // a while loop conditioned on the size of both sets and a subsequent loop to use + // unpaired items. + while (large != n && small != 0) { + // Index of the small and the large probabilities. + val j = indices[--small] + val k = indices[large++] + + // Optimisation for zero-padded input: + // p(j) = 0 above the last nonZeroIndex + if (j > nonZeroIndex) + // The entire amount for the section is taken from the alias. + remainingProbabilities[k] -= mean + else { + val pj = remainingProbabilities[j] + // Item j is a small probability that is below the mean. + // Compute the weight of the section for item j: pj / mean. + // This is scaled by 2^53 and the ceiling function used to round-up + // the probability to a numerator of a fraction in the range [1,2^53]. + // Ceiling ensures non-zero values. + probability[j] = ceil(CONVERT_TO_NUMERATOR * (pj / mean)).toLong() + // The remaining amount for the section is taken from the alias. + // Effectively: probabilities[k] -= (mean - pj) + remainingProbabilities[k] += pj - mean + } + + // If not j then the alias is k + alias[j] = k + + // Add the remaining probability from large to the appropriate list. + if (remainingProbabilities[k] >= mean) indices[--large] = k else indices[small++] = k + } + + // Final loop conditions to consume unpaired items. + // Note: The large set should never be non-empty but this can occur due to round-off + // error so consume from both. + fillTable(probability, alias, indices, 0, small) + fillTable(probability, alias, indices, large, n) + + // Change the algorithm for small power of 2 sized tables + return if (isSmallPowerOf2(n)) { + SmallTableAliasMethodDiscreteSampler(probability, alias) + } else { + AliasMethodDiscreteSampler(probability, alias) + } + } } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt new file mode 100644 index 000000000..1f1871cbb --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt @@ -0,0 +1,52 @@ +package space.kscience.kmath.samplers + +import space.kscience.kmath.chains.BlockingDoubleChain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.structures.DoubleBuffer +import kotlin.math.* + +/** + * [Box-Muller algorithm](https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform) for sampling from a Gaussian + * distribution. + * + * Based on Commons RNG implementation. + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.html]. + */ + +public object BoxMullerSampler : NormalizedGaussianSampler { + override fun sample(generator: RandomGenerator): BlockingDoubleChain = object : BlockingDoubleChain { + var state = Double.NaN + + override fun nextBufferBlocking(size: Int): DoubleBuffer { + val xs = generator.nextDoubleBuffer(size) + val ys = generator.nextDoubleBuffer(size) + + return DoubleBuffer(size) { index -> + if (state.isNaN()) { + // Generate a pair of Gaussian numbers. + val x = xs[index] + val y = ys[index] + val alpha = 2 * PI * x + val r = sqrt(-2 * ln(y)) + + // Keep second element of the pair for next invocation. + state = r * sin(alpha) + + // Return the first element of the generated pair. + r * cos(alpha) + } else { + // Use the second element of the pair (generated at the + // previous invocation). + state.also { + // Both elements of the pair have been used. + state = Double.NaN + } + } + } + } + + + override suspend fun fork(): BlockingDoubleChain = sample(generator.fork()) + } + +} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ConstantSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ConstantSampler.kt new file mode 100644 index 000000000..0f8d13305 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ConstantSampler.kt @@ -0,0 +1,13 @@ +package space.kscience.kmath.samplers + +import space.kscience.kmath.chains.BlockingBufferChain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.structures.Buffer + +public class ConstantSampler(public val const: T) : Sampler { + override fun sample(generator: RandomGenerator): BlockingBufferChain = object : BlockingBufferChain { + override fun nextBufferBlocking(size: Int): Buffer = Buffer.boxing(size) { const } + override suspend fun fork(): BlockingBufferChain = this + } +} \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt new file mode 100644 index 000000000..26047830c --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt @@ -0,0 +1,34 @@ +package space.kscience.kmath.samplers + +import space.kscience.kmath.chains.BlockingDoubleChain +import space.kscience.kmath.chains.map +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler + +/** + * Sampling from a Gaussian distribution with given mean and standard deviation. + * + * Based on Commons RNG implementation. + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/GaussianSampler.html]. + * + * @property mean the mean of the distribution. + * @property standardDeviation the variance of the distribution. + */ +public class GaussianSampler( + public val mean: Double, + public val standardDeviation: Double, + private val normalized: NormalizedGaussianSampler = BoxMullerSampler +) : Sampler { + + init { + require(standardDeviation > 0.0) { "standard deviation is not strictly positive: $standardDeviation" } + } + + public override fun sample(generator: RandomGenerator): BlockingDoubleChain = normalized + .sample(generator) + .map { standardDeviation * it + mean } + + override fun toString(): String = "N($mean, $standardDeviation)" + + public companion object +} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt new file mode 100644 index 000000000..0f8e6b089 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt @@ -0,0 +1,68 @@ +package space.kscience.kmath.samplers + +import space.kscience.kmath.chains.BlockingIntChain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.structures.IntBuffer +import kotlin.math.exp + +/** + * Sampler for the Poisson distribution. + * - Kemp, A, W, (1981) Efficient Generation of Logarithmically Distributed Pseudo-Random Variables. Journal of the Royal Statistical Society. Vol. 30, No. 3, pp. 249-253. + * This sampler is suitable for mean < 40. For large means, LargeMeanPoissonSampler should be used instead. + * + * Note: The algorithm uses a recurrence relation to compute the Poisson probability and a rolling summation for the cumulative probability. When the mean is large the initial probability (Math.exp(-mean)) is zero and an exception is raised by the constructor. + * + * Sampling uses 1 call to UniformRandomProvider.nextDouble(). This method provides an alternative to the SmallMeanPoissonSampler for slow generators of double. + * + * Based on Commons RNG implementation. + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.html]. + */ +public class KempSmallMeanPoissonSampler internal constructor( + private val p0: Double, + private val mean: Double, +) : Sampler { + public override fun sample(generator: RandomGenerator): BlockingIntChain = object : BlockingIntChain { + override fun nextBlocking(): Int { + //TODO move to nextBufferBlocking + // Note on the algorithm: + // - X is the unknown sample deviate (the output of the algorithm) + // - x is the current value from the distribution + // - p is the probability of the current value x, p(X=x) + // - u is effectively the cumulative probability that the sample X + // is equal or above the current value x, p(X>=x) + // So if p(X>=x) > p(X=x) the sample must be above x, otherwise it is x + var u = generator.nextDouble() + var x = 0 + var p = p0 + + while (u > p) { + u -= p + // Compute the next probability using a recurrence relation. + // p(x+1) = p(x) * mean / (x+1) + p *= mean / ++x + // The algorithm listed in Kemp (1981) does not check that the rolling probability + // is positive. This check is added to ensure no errors when the limit of the summation + // 1 - sum(p(x)) is above 0 due to cumulative error in floating point arithmetic. + if (p == 0.0) return x + } + + return x + } + + override fun nextBufferBlocking(size: Int): IntBuffer = IntBuffer(size) { nextBlocking() } + + override suspend fun fork(): BlockingIntChain = sample(generator.fork()) + } + + public override fun toString(): String = "Kemp Small Mean Poisson deviate" +} + +public fun KempSmallMeanPoissonSampler(mean: Double): KempSmallMeanPoissonSampler { + require(mean > 0) { "Mean is not strictly positive: $mean" } + val p0 = exp(-mean) + // Probability must be positive. As mean increases then p(0) decreases. + require(p0 > 0) { "No probability for mean: $mean" } + return KempSmallMeanPoissonSampler(p0, mean) +} + diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt new file mode 100644 index 000000000..b93bcc106 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt @@ -0,0 +1,61 @@ +package space.kscience.kmath.samplers + +import space.kscience.kmath.chains.BlockingDoubleChain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.structures.DoubleBuffer +import kotlin.math.ln +import kotlin.math.sqrt + +/** + * [Marsaglia polar method](https://en.wikipedia.org/wiki/Marsaglia_polar_method) for sampling from a Gaussian + * distribution with mean 0 and standard deviation 1. This is a variation of the algorithm implemented in + * [BoxMullerNormalizedGaussianSampler]. + * + * Based on Commons RNG implementation. + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.html] + */ +public object MarsagliaNormalizedGaussianSampler : NormalizedGaussianSampler { + + override fun sample(generator: RandomGenerator): BlockingDoubleChain = object : BlockingDoubleChain { + var nextGaussian = Double.NaN + + override fun nextBlocking(): Double { + return if (nextGaussian.isNaN()) { + val alpha: Double + var x: Double + + // Rejection scheme for selecting a pair that lies within the unit circle. + while (true) { + // Generate a pair of numbers within [-1 , 1). + x = 2.0 * generator.nextDouble() - 1.0 + val y = 2.0 * generator.nextDouble() - 1.0 + val r2 = x * x + y * y + + if (r2 < 1 && r2 > 0) { + // Pair (x, y) is within unit circle. + alpha = sqrt(-2 * ln(r2) / r2) + // Keep second element of the pair for next invocation. + nextGaussian = alpha * y + // Return the first element of the generated pair. + break + } + // Pair is not within the unit circle: Generate another one. + } + + // Return the first element of the generated pair. + alpha * x + } else { + // Use the second element of the pair (generated at the + // previous invocation). + val r = nextGaussian + // Both elements of the pair have been used. + nextGaussian = Double.NaN + r + } + } + + override fun nextBufferBlocking(size: Int): DoubleBuffer = DoubleBuffer(size) { nextBlocking() } + + override suspend fun fork(): BlockingDoubleChain = sample(generator.fork()) + } +} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt new file mode 100644 index 000000000..6d3daadab --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt @@ -0,0 +1,18 @@ +package space.kscience.kmath.samplers + +import space.kscience.kmath.chains.BlockingDoubleChain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler + +public interface BlockingDoubleSampler: Sampler{ + override fun sample(generator: RandomGenerator): BlockingDoubleChain +} + + +/** + * Marker interface for a sampler that generates values from an N(0,1) + * [Gaussian distribution](https://en.wikipedia.org/wiki/Normal_distribution). + */ +public fun interface NormalizedGaussianSampler : BlockingDoubleSampler{ + public companion object +} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt new file mode 100644 index 000000000..c2e8e2c1c --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt @@ -0,0 +1,203 @@ +package space.kscience.kmath.samplers + +import space.kscience.kmath.chains.BlockingIntChain +import space.kscience.kmath.internal.InternalUtils +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.Sampler +import space.kscience.kmath.structures.IntBuffer +import kotlin.math.* + + +private const val PIVOT = 40.0 + +/** + * Sampler for the Poisson distribution. + * - For small means, a Poisson process is simulated using uniform deviates, as described in + * Knuth (1969). Seminumerical Algorithms. The Art of Computer Programming, Volume 2. Chapter 3.4.1.F.3 + * Important integer-valued distributions: The Poisson distribution. Addison Wesley. + * The Poisson process (and hence, the returned value) is bounded by 1000 * mean. + * - For large means, we use the rejection algorithm described in + * Devroye, Luc. (1981). The Computer Generation of Poisson Random Variables Computing vol. 26 pp. 197-207. + * + * Based on Commons RNG implementation. + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/PoissonSampler.html]. + */ +@Suppress("FunctionName") +public fun PoissonSampler(mean: Double): Sampler { + return if (mean < PIVOT) SmallMeanPoissonSampler(mean) else LargeMeanPoissonSampler(mean) +} + +/** + * Sampler for the Poisson distribution. + * - For small means, a Poisson process is simulated using uniform deviates, as described in + * Knuth (1969). Seminumerical Algorithms. The Art of Computer Programming, Volume 2. Chapter 3.4.1.F.3 Important + * integer-valued distributions: The Poisson distribution. Addison Wesley. + * - The Poisson process (and hence, the returned value) is bounded by 1000 * mean. + * This sampler is suitable for mean < 40. For large means, [LargeMeanPoissonSampler] should be used instead. + * + * Based on Commons RNG implementation. + * + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/SmallMeanPoissonSampler.html]. + */ +public class SmallMeanPoissonSampler(public val mean: Double) : Sampler { + + init { + require(mean > 0) { "mean is not strictly positive: $mean" } + } + + private val p0: Double = exp(-mean) + + private val limit: Int = if (p0 > 0) { + ceil(1000 * mean) + } else { + throw IllegalArgumentException("No p(x=0) probability for mean: $mean") + }.toInt() + + public override fun sample(generator: RandomGenerator): BlockingIntChain = object : BlockingIntChain { + override fun nextBlocking(): Int { + var n = 0 + var r = 1.0 + + while (n < limit) { + r *= generator.nextDouble() + if (r >= p0) n++ else break + } + + return n + } + + override fun nextBufferBlocking(size: Int): IntBuffer = IntBuffer(size) { nextBlocking() } + + override suspend fun fork(): BlockingIntChain = sample(generator.fork()) + } + + public override fun toString(): String = "Small Mean Poisson deviate" +} + + +/** + * Sampler for the Poisson distribution. + * - For large means, we use the rejection algorithm described in + * Devroye, Luc. (1981).The Computer Generation of Poisson Random Variables + * Computing vol. 26 pp. 197-207. + * + * This sampler is suitable for mean >= 40. + * + * Based on Commons RNG implementation. + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/LargeMeanPoissonSampler.html]. + */ +public class LargeMeanPoissonSampler(public val mean: Double) : Sampler { + + init { + require(mean >= 1) { "mean is not >= 1: $mean" } + // The algorithm is not valid if Math.floor(mean) is not an integer. + require(mean <= MAX_MEAN) { "mean $mean > $MAX_MEAN" } + } + + private val factorialLog: InternalUtils.FactorialLog = NO_CACHE_FACTORIAL_LOG + private val lambda: Double = floor(mean) + private val logLambda: Double = ln(lambda) + private val logLambdaFactorial: Double = getFactorialLog(lambda.toInt()) + private val delta: Double = sqrt(lambda * ln(32 * lambda / PI + 1)) + private val halfDelta: Double = delta / 2 + private val twolpd: Double = 2 * lambda + delta + private val c1: Double = 1 / (8 * lambda) + private val a1: Double = sqrt(PI * twolpd) * exp(c1) + private val a2: Double = twolpd / delta * exp(-delta * (1 + delta) / twolpd) + private val aSum: Double = a1 + a2 + 1 + private val p1: Double = a1 / aSum + private val p2: Double = a2 / aSum + + public override fun sample(generator: RandomGenerator): BlockingIntChain = object : BlockingIntChain { + override fun nextBlocking(): Int { + val exponential = AhrensDieterExponentialSampler(1.0).sample(generator) + val gaussian = ZigguratNormalizedGaussianSampler.sample(generator) + + val smallMeanPoissonSampler = if (mean - lambda < Double.MIN_VALUE) { + null + } else { + KempSmallMeanPoissonSampler(mean - lambda).sample(generator) + } + + val y2 = smallMeanPoissonSampler?.nextBlocking() ?: 0 + var x: Double + var y: Double + var v: Double + var a: Int + var t: Double + var qr: Double + var qa: Double + + while (true) { + // Step 1: + val u = generator.nextDouble() + + if (u <= p1) { + // Step 2: + val n = gaussian.nextBlocking() + x = n * sqrt(lambda + halfDelta) - 0.5 + if (x > delta || x < -lambda) continue + y = if (x < 0) floor(x) else ceil(x) + val e = exponential.nextBlocking() + v = -e - 0.5 * n * n + c1 + } else { + // Step 3: + if (u > p1 + p2) { + y = lambda + break + } + + x = delta + twolpd / delta * exponential.nextBlocking() + y = ceil(x) + v = -exponential.nextBlocking() - delta * (x + 1) / twolpd + } + + // The Squeeze Principle + // Step 4.1: + a = if (x < 0) 1 else 0 + t = y * (y + 1) / (2 * lambda) + + // Step 4.2 + if (v < -t && a == 0) { + y += lambda + break + } + + // Step 4.3: + qr = t * ((2 * y + 1) / (6 * lambda) - 1) + qa = qr - t * t / (3 * (lambda + a * (y + 1))) + + // Step 4.4: + if (v < qa) { + y += lambda + break + } + + // Step 4.5: + if (v > qr) continue + + // Step 4.6: + if (v < y * logLambda - getFactorialLog((y + lambda).toInt()) + logLambdaFactorial) { + y += lambda + break + } + } + + return min(y2 + y.toLong(), Int.MAX_VALUE.toLong()).toInt() + } + + override fun nextBufferBlocking(size: Int): IntBuffer = IntBuffer(size) { nextBlocking() } + + override suspend fun fork(): BlockingIntChain = sample(generator.fork()) + } + + private fun getFactorialLog(n: Int): Double = factorialLog.value(n) + public override fun toString(): String = "Large Mean Poisson deviate" + + public companion object { + private const val MAX_MEAN: Double = 0.5 * Int.MAX_VALUE + private val NO_CACHE_FACTORIAL_LOG: InternalUtils.FactorialLog = InternalUtils.FactorialLog.create() + } +} + + diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt new file mode 100644 index 000000000..70f5c248d --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt @@ -0,0 +1,88 @@ +package space.kscience.kmath.samplers + +import space.kscience.kmath.chains.BlockingDoubleChain +import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.structures.DoubleBuffer +import kotlin.math.* + +/** + * [Marsaglia and Tsang "Ziggurat"](https://en.wikipedia.org/wiki/Ziggurat_algorithm) method for sampling from a + * Gaussian distribution with mean 0 and standard deviation 1. The algorithm is explained in this paper and this + * implementation has been adapted from the C code provided therein. + * + * Based on Commons RNG implementation. + * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.html]. + */ +public object ZigguratNormalizedGaussianSampler : NormalizedGaussianSampler { + + private const val R: Double = 3.442619855899 + private const val ONE_OVER_R: Double = 1 / R + private const val V: Double = 9.91256303526217e-3 + private val MAX: Double = 2.0.pow(63.0) + private val ONE_OVER_MAX: Double = 1.0 / MAX + private const val LEN: Int = 128 + private const val LAST: Int = LEN - 1 + private val K: LongArray = LongArray(LEN) + private val W: DoubleArray = DoubleArray(LEN) + private val F: DoubleArray = DoubleArray(LEN) + + init { + // Filling the tables. + var d = R + var t = d + var fd = gauss(d) + val q = V / fd + K[0] = (d / q * MAX).toLong() + K[1] = 0 + W[0] = q * ONE_OVER_MAX + W[LAST] = d * ONE_OVER_MAX + F[0] = 1.0 + F[LAST] = fd + + (LAST - 1 downTo 1).forEach { i -> + d = sqrt(-2 * ln(V / d + fd)) + fd = gauss(d) + K[i + 1] = (d / t * MAX).toLong() + t = d + F[i] = fd + W[i] = d * ONE_OVER_MAX + } + } + + private fun gauss(x: Double): Double = exp(-0.5 * x * x) + + private fun sampleOne(generator: RandomGenerator): Double { + val j = generator.nextLong() + val i = (j and LAST.toLong()).toInt() + return if (abs(j) < K[i]) j * W[i] else fix(generator, j, i) + } + + override fun sample(generator: RandomGenerator): BlockingDoubleChain = object : BlockingDoubleChain { + override fun nextBufferBlocking(size: Int): DoubleBuffer = DoubleBuffer(size) { sampleOne(generator) } + + override suspend fun fork(): BlockingDoubleChain = sample(generator.fork()) + } + + + private fun fix(generator: RandomGenerator, hz: Long, iz: Int): Double { + var x = hz * W[iz] + + return when { + iz == 0 -> { + var y: Double + + do { + y = -ln(generator.nextDouble()) + x = -ln(generator.nextDouble()) * ONE_OVER_R + } while (y + y < x * x) + + val out = R + x + if (hz > 0) out else -out + } + + F[iz] + generator.nextDouble() * (F[iz - 1] - F[iz]) < gauss(x) -> x + else -> sampleOne(generator) + } + } + +} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt index 2f117a035..9e3e265dc 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.stat import space.kscience.kmath.chains.BlockingDoubleChain -import space.kscience.kmath.chains.BlockingIntChain import space.kscience.kmath.chains.Chain +import space.kscience.kmath.structures.DoubleBuffer /** * A possibly stateful chain producing random values. @@ -11,12 +11,24 @@ import space.kscience.kmath.chains.Chain */ public class RandomChain( public val generator: RandomGenerator, - private val gen: suspend RandomGenerator.() -> R + private val gen: suspend RandomGenerator.() -> R, ) : Chain { override suspend fun next(): R = generator.gen() - override fun fork(): Chain = RandomChain(generator.fork(), gen) + override suspend fun fork(): Chain = RandomChain(generator.fork(), gen) +} + +/** + * Create a generic random chain with provided [generator] + */ +public fun RandomGenerator.chain(generator: suspend RandomGenerator.() -> R): RandomChain = RandomChain(this, generator) + +/** + * A type-specific double chunk random chain + */ +public class UniformDoubleChain(public val generator: RandomGenerator) : BlockingDoubleChain { + public override fun nextBufferBlocking(size: Int): DoubleBuffer = generator.nextDoubleBuffer(size) + override suspend fun nextBuffer(size: Int): DoubleBuffer = nextBufferBlocking(size) + + override suspend fun fork(): UniformDoubleChain = UniformDoubleChain(generator.fork()) } -public fun RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain = RandomChain(this, gen) -public fun Chain.blocking(): BlockingDoubleChain = object : Chain by this, BlockingDoubleChain {} -public fun Chain.blocking(): BlockingIntChain = object : Chain by this, BlockingIntChain {} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt index bad2334e9..c40513efc 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.stat +import space.kscience.kmath.structures.DoubleBuffer import kotlin.random.Random /** @@ -16,6 +17,11 @@ public interface RandomGenerator { */ public fun nextDouble(): Double + /** + * A chunk of doubles of given [size] + */ + public fun nextDoubleBuffer(size: Int): DoubleBuffer = DoubleBuffer(size) { nextDouble() } + /** * Gets the next random `Int` from the random number generator. * diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt similarity index 54% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt index 095182160..8d024b2b9 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt @@ -3,16 +3,13 @@ package space.kscience.kmath.stat import kotlinx.coroutines.flow.first import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.collect -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.IntBuffer -import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.* import kotlin.jvm.JvmName /** - * Sampler that generates chains of values of type [T]. + * Sampler that generates chains of values of type [T] in a chain of type [C]. */ -public fun interface Sampler { +public fun interface Sampler { /** * Generates a chain of samples. * @@ -22,39 +19,6 @@ public fun interface Sampler { public fun sample(generator: RandomGenerator): Chain } -/** - * A distribution of typed objects. - */ -public interface Distribution : Sampler { - /** - * A probability value for given argument [arg]. - * For continuous distributions returns PDF - */ - public fun probability(arg: T): Double - - public override fun sample(generator: RandomGenerator): Chain - - /** - * An empty companion. Distribution factories should be written as its extensions - */ - public companion object -} - -public interface UnivariateDistribution> : Distribution { - /** - * Cumulative distribution for ordered parameter (CDF) - */ - public fun cumulative(arg: T): Double -} - -/** - * Compute probability integral in an interval - */ -public fun > UnivariateDistribution.integral(from: T, to: T): Double { - require(to > from) - return cumulative(to) - cumulative(from) -} - /** * Sample a bunch of values */ @@ -71,7 +35,7 @@ public fun Sampler.sampleBuffer( //clear list from previous run tmp.clear() //Fill list - repeat(size) { tmp += chain.next() } + repeat(size) { tmp.add(chain.next()) } //return new buffer with elements from tmp bufferFactory(size) { tmp[it] } } @@ -87,7 +51,7 @@ public suspend fun Sampler.next(generator: RandomGenerator): T = sa */ @JvmName("sampleRealBuffer") public fun Sampler.sampleBuffer(generator: RandomGenerator, size: Int): Chain> = - sampleBuffer(generator, size, MutableBuffer.Companion::double) + sampleBuffer(generator, size, ::DoubleBuffer) /** * Generates [size] integer samples and chunks them into some buffers. diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt index 689182115..67f55aea6 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt @@ -81,7 +81,7 @@ public class Mean( public companion object { //TODO replace with optimized version which respects overflow - public val real: Mean = Mean(DoubleField) { sum, count -> sum / count } + public val double: Mean = Mean(DoubleField) { sum, count -> sum / count } public val int: Mean = Mean(IntRing) { sum, count -> sum / count } public val long: Mean = Mean(LongRing) { sum, count -> sum / count } } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt index 4fc0905b8..4fc759e0c 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt @@ -2,6 +2,8 @@ package space.kscience.kmath.stat import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.SimpleChain +import space.kscience.kmath.distributions.Distribution +import space.kscience.kmath.distributions.UnivariateDistribution public class UniformDistribution(public val range: ClosedFloatingPointRange) : UnivariateDistribution { private val length: Double = range.endInclusive - range.start diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt deleted file mode 100644 index 504c6b881..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/AhrensDieterExponentialSampler.kt +++ /dev/null @@ -1,73 +0,0 @@ -package space.kscience.kmath.stat.samplers - -import space.kscience.kmath.chains.Chain -import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler -import space.kscience.kmath.stat.chain -import space.kscience.kmath.stat.internal.InternalUtils -import kotlin.math.ln -import kotlin.math.pow - -/** - * Sampling from an [exponential distribution](http://mathworld.wolfram.com/ExponentialDistribution.html). - * - * Based on Commons RNG implementation. - * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.html]. - */ -public class AhrensDieterExponentialSampler private constructor(public val mean: Double) : Sampler { - public override fun sample(generator: RandomGenerator): Chain = generator.chain { - // Step 1: - var a = 0.0 - var u = nextDouble() - - // Step 2 and 3: - while (u < 0.5) { - a += EXPONENTIAL_SA_QI[0] - u *= 2.0 - } - - // Step 4 (now u >= 0.5): - u += u - 1 - // Step 5: - if (u <= EXPONENTIAL_SA_QI[0]) return@chain mean * (a + u) - // Step 6: - var i = 0 // Should be 1, be we iterate before it in while using 0. - var u2 = nextDouble() - var umin = u2 - - // Step 7 and 8: - do { - ++i - u2 = nextDouble() - if (u2 < umin) umin = u2 - // Step 8: - } while (u > EXPONENTIAL_SA_QI[i]) // Ensured to exit since EXPONENTIAL_SA_QI[MAX] = 1. - - mean * (a + umin * EXPONENTIAL_SA_QI[0]) - } - - override fun toString(): String = "Ahrens-Dieter Exponential deviate" - - public companion object { - private val EXPONENTIAL_SA_QI by lazy { DoubleArray(16) } - - init { - /** - * Filling EXPONENTIAL_SA_QI table. - * Note that we don't want qi = 0 in the table. - */ - val ln2 = ln(2.0) - var qi = 0.0 - - EXPONENTIAL_SA_QI.indices.forEach { i -> - qi += ln2.pow(i + 1.0) / InternalUtils.factorial(i + 1) - EXPONENTIAL_SA_QI[i] = qi - } - } - - public fun of(mean: Double): AhrensDieterExponentialSampler { - require(mean > 0) { "mean is not strictly positive: $mean" } - return AhrensDieterExponentialSampler(mean) - } - } -} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt deleted file mode 100644 index 04beb448d..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/BoxMullerNormalizedGaussianSampler.kt +++ /dev/null @@ -1,48 +0,0 @@ -package space.kscience.kmath.stat.samplers - -import space.kscience.kmath.chains.Chain -import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler -import space.kscience.kmath.stat.chain -import kotlin.math.* - -/** - * [Box-Muller algorithm](https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform) for sampling from a Gaussian - * distribution. - * - * Based on Commons RNG implementation. - * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.html]. - */ -public class BoxMullerNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { - private var nextGaussian: Double = Double.NaN - - public override fun sample(generator: RandomGenerator): Chain = generator.chain { - val random: Double - - if (nextGaussian.isNaN()) { - // Generate a pair of Gaussian numbers. - val x = nextDouble() - val y = nextDouble() - val alpha = 2 * PI * x - val r = sqrt(-2 * ln(y)) - // Return the first element of the generated pair. - random = r * cos(alpha) - // Keep second element of the pair for next invocation. - nextGaussian = r * sin(alpha) - } else { - // Use the second element of the pair (generated at the - // previous invocation). - random = nextGaussian - // Both elements of the pair have been used. - nextGaussian = Double.NaN - } - - random - } - - public override fun toString(): String = "Box-Muller normalized Gaussian deviate" - - public companion object { - public fun of(): BoxMullerNormalizedGaussianSampler = BoxMullerNormalizedGaussianSampler() - } -} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/GaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/GaussianSampler.kt deleted file mode 100644 index eba26cfb5..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/GaussianSampler.kt +++ /dev/null @@ -1,43 +0,0 @@ -package space.kscience.kmath.stat.samplers - -import space.kscience.kmath.chains.Chain -import space.kscience.kmath.chains.map -import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler - -/** - * Sampling from a Gaussian distribution with given mean and standard deviation. - * - * Based on Commons RNG implementation. - * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/GaussianSampler.html]. - * - * @property mean the mean of the distribution. - * @property standardDeviation the variance of the distribution. - */ -public class GaussianSampler private constructor( - public val mean: Double, - public val standardDeviation: Double, - private val normalized: NormalizedGaussianSampler -) : Sampler { - public override fun sample(generator: RandomGenerator): Chain = normalized - .sample(generator) - .map { standardDeviation * it + mean } - - override fun toString(): String = "Gaussian deviate [$normalized]" - - public companion object { - public fun of( - mean: Double, - standardDeviation: Double, - normalized: NormalizedGaussianSampler = ZigguratNormalizedGaussianSampler.of() - ): GaussianSampler { - require(standardDeviation > 0.0) { "standard deviation is not strictly positive: $standardDeviation" } - - return GaussianSampler( - mean, - standardDeviation, - normalized - ) - } - } -} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt deleted file mode 100644 index 1d7f90023..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/KempSmallMeanPoissonSampler.kt +++ /dev/null @@ -1,63 +0,0 @@ -package space.kscience.kmath.stat.samplers - -import space.kscience.kmath.chains.Chain -import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler -import space.kscience.kmath.stat.chain -import kotlin.math.exp - -/** - * Sampler for the Poisson distribution. - * - Kemp, A, W, (1981) Efficient Generation of Logarithmically Distributed Pseudo-Random Variables. Journal of the Royal Statistical Society. Vol. 30, No. 3, pp. 249-253. - * This sampler is suitable for mean < 40. For large means, LargeMeanPoissonSampler should be used instead. - * - * Note: The algorithm uses a recurrence relation to compute the Poisson probability and a rolling summation for the cumulative probability. When the mean is large the initial probability (Math.exp(-mean)) is zero and an exception is raised by the constructor. - * - * Sampling uses 1 call to UniformRandomProvider.nextDouble(). This method provides an alternative to the SmallMeanPoissonSampler for slow generators of double. - * - * Based on Commons RNG implementation. - * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/KempSmallMeanPoissonSampler.html]. - */ -public class KempSmallMeanPoissonSampler private constructor( - private val p0: Double, - private val mean: Double -) : Sampler { - public override fun sample(generator: RandomGenerator): Chain = generator.chain { - // Note on the algorithm: - // - X is the unknown sample deviate (the output of the algorithm) - // - x is the current value from the distribution - // - p is the probability of the current value x, p(X=x) - // - u is effectively the cumulative probability that the sample X - // is equal or above the current value x, p(X>=x) - // So if p(X>=x) > p(X=x) the sample must be above x, otherwise it is x - var u = nextDouble() - var x = 0 - var p = p0 - - while (u > p) { - u -= p - // Compute the next probability using a recurrence relation. - // p(x+1) = p(x) * mean / (x+1) - p *= mean / ++x - // The algorithm listed in Kemp (1981) does not check that the rolling probability - // is positive. This check is added to ensure no errors when the limit of the summation - // 1 - sum(p(x)) is above 0 due to cumulative error in floating point arithmetic. - if (p == 0.0) return@chain x - } - - x - } - - public override fun toString(): String = "Kemp Small Mean Poisson deviate" - - public companion object { - public fun of(mean: Double): KempSmallMeanPoissonSampler { - require(mean > 0) { "Mean is not strictly positive: $mean" } - val p0 = exp(-mean) - // Probability must be positive. As mean increases then p(0) decreases. - require(p0 > 0) { "No probability for mean: $mean" } - return KempSmallMeanPoissonSampler(p0, mean) - } - } -} - diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt deleted file mode 100644 index de1e7cc89..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/LargeMeanPoissonSampler.kt +++ /dev/null @@ -1,130 +0,0 @@ -package space.kscience.kmath.stat.samplers - -import space.kscience.kmath.chains.Chain -import space.kscience.kmath.chains.ConstantChain -import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler -import space.kscience.kmath.stat.chain -import space.kscience.kmath.stat.internal.InternalUtils -import space.kscience.kmath.stat.next -import kotlin.math.* - -/** - * Sampler for the Poisson distribution. - * - For large means, we use the rejection algorithm described in - * Devroye, Luc. (1981).The Computer Generation of Poisson Random Variables - * Computing vol. 26 pp. 197-207. - * - * This sampler is suitable for mean >= 40. - * - * Based on Commons RNG implementation. - * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/LargeMeanPoissonSampler.html]. - */ -public class LargeMeanPoissonSampler private constructor(public val mean: Double) : Sampler { - private val exponential: Sampler = AhrensDieterExponentialSampler.of(1.0) - private val gaussian: Sampler = ZigguratNormalizedGaussianSampler.of() - private val factorialLog: InternalUtils.FactorialLog = NO_CACHE_FACTORIAL_LOG - private val lambda: Double = floor(mean) - private val logLambda: Double = ln(lambda) - private val logLambdaFactorial: Double = getFactorialLog(lambda.toInt()) - private val delta: Double = sqrt(lambda * ln(32 * lambda / PI + 1)) - private val halfDelta: Double = delta / 2 - private val twolpd: Double = 2 * lambda + delta - private val c1: Double = 1 / (8 * lambda) - private val a1: Double = sqrt(PI * twolpd) * exp(c1) - private val a2: Double = twolpd / delta * exp(-delta * (1 + delta) / twolpd) - private val aSum: Double = a1 + a2 + 1 - private val p1: Double = a1 / aSum - private val p2: Double = a2 / aSum - - private val smallMeanPoissonSampler: Sampler = if (mean - lambda < Double.MIN_VALUE) - NO_SMALL_MEAN_POISSON_SAMPLER - else // Not used. - KempSmallMeanPoissonSampler.of(mean - lambda) - - public override fun sample(generator: RandomGenerator): Chain = generator.chain { - // This will never be null. It may be a no-op delegate that returns zero. - val y2 = smallMeanPoissonSampler.next(generator) - var x: Double - var y: Double - var v: Double - var a: Int - var t: Double - var qr: Double - var qa: Double - - while (true) { - // Step 1: - val u = generator.nextDouble() - - if (u <= p1) { - // Step 2: - val n = gaussian.next(generator) - x = n * sqrt(lambda + halfDelta) - 0.5 - if (x > delta || x < -lambda) continue - y = if (x < 0) floor(x) else ceil(x) - val e = exponential.next(generator) - v = -e - 0.5 * n * n + c1 - } else { - // Step 3: - if (u > p1 + p2) { - y = lambda - break - } - - x = delta + twolpd / delta * exponential.next(generator) - y = ceil(x) - v = -exponential.next(generator) - delta * (x + 1) / twolpd - } - - // The Squeeze Principle - // Step 4.1: - a = if (x < 0) 1 else 0 - t = y * (y + 1) / (2 * lambda) - - // Step 4.2 - if (v < -t && a == 0) { - y += lambda - break - } - - // Step 4.3: - qr = t * ((2 * y + 1) / (6 * lambda) - 1) - qa = qr - t * t / (3 * (lambda + a * (y + 1))) - - // Step 4.4: - if (v < qa) { - y += lambda - break - } - - // Step 4.5: - if (v > qr) continue - - // Step 4.6: - if (v < y * logLambda - getFactorialLog((y + lambda).toInt()) + logLambdaFactorial) { - y += lambda - break - } - } - - min(y2 + y.toLong(), Int.MAX_VALUE.toLong()).toInt() - } - - private fun getFactorialLog(n: Int): Double = factorialLog.value(n) - public override fun toString(): String = "Large Mean Poisson deviate" - - public companion object { - private const val MAX_MEAN: Double = 0.5 * Int.MAX_VALUE - private val NO_CACHE_FACTORIAL_LOG: InternalUtils.FactorialLog = InternalUtils.FactorialLog.create() - - private val NO_SMALL_MEAN_POISSON_SAMPLER: Sampler = Sampler { ConstantChain(0) } - - public fun of(mean: Double): LargeMeanPoissonSampler { - require(mean >= 1) { "mean is not >= 1: $mean" } - // The algorithm is not valid if Math.floor(mean) is not an integer. - require(mean <= MAX_MEAN) { "mean $mean > $MAX_MEAN" } - return LargeMeanPoissonSampler(mean) - } - } -} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt deleted file mode 100644 index 8a659642f..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/MarsagliaNormalizedGaussianSampler.kt +++ /dev/null @@ -1,61 +0,0 @@ -package space.kscience.kmath.stat.samplers - -import space.kscience.kmath.chains.Chain -import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler -import space.kscience.kmath.stat.chain -import kotlin.math.ln -import kotlin.math.sqrt - -/** - * [Marsaglia polar method](https://en.wikipedia.org/wiki/Marsaglia_polar_method) for sampling from a Gaussian - * distribution with mean 0 and standard deviation 1. This is a variation of the algorithm implemented in - * [BoxMullerNormalizedGaussianSampler]. - * - * Based on Commons RNG implementation. - * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/MarsagliaNormalizedGaussianSampler.html] - */ -public class MarsagliaNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler { - private var nextGaussian = Double.NaN - - public override fun sample(generator: RandomGenerator): Chain = generator.chain { - if (nextGaussian.isNaN()) { - val alpha: Double - var x: Double - - // Rejection scheme for selecting a pair that lies within the unit circle. - while (true) { - // Generate a pair of numbers within [-1 , 1). - x = 2.0 * generator.nextDouble() - 1.0 - val y = 2.0 * generator.nextDouble() - 1.0 - val r2 = x * x + y * y - - if (r2 < 1 && r2 > 0) { - // Pair (x, y) is within unit circle. - alpha = sqrt(-2 * ln(r2) / r2) - // Keep second element of the pair for next invocation. - nextGaussian = alpha * y - // Return the first element of the generated pair. - break - } - // Pair is not within the unit circle: Generate another one. - } - - // Return the first element of the generated pair. - alpha * x - } else { - // Use the second element of the pair (generated at the - // previous invocation). - val r = nextGaussian - // Both elements of the pair have been used. - nextGaussian = Double.NaN - r - } - } - - public override fun toString(): String = "Box-Muller (with rejection) normalized Gaussian deviate" - - public companion object { - public fun of(): MarsagliaNormalizedGaussianSampler = MarsagliaNormalizedGaussianSampler() - } -} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt deleted file mode 100644 index 4eb3d60e0..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/NormalizedGaussianSampler.kt +++ /dev/null @@ -1,9 +0,0 @@ -package space.kscience.kmath.stat.samplers - -import space.kscience.kmath.stat.Sampler - -/** - * Marker interface for a sampler that generates values from an N(0,1) - * [Gaussian distribution](https://en.wikipedia.org/wiki/Normal_distribution). - */ -public interface NormalizedGaussianSampler : Sampler diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/PoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/PoissonSampler.kt deleted file mode 100644 index 0c0234892..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/PoissonSampler.kt +++ /dev/null @@ -1,30 +0,0 @@ -package space.kscience.kmath.stat.samplers - -import space.kscience.kmath.chains.Chain -import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler - -/** - * Sampler for the Poisson distribution. - * - For small means, a Poisson process is simulated using uniform deviates, as described in - * Knuth (1969). Seminumerical Algorithms. The Art of Computer Programming, Volume 2. Chapter 3.4.1.F.3 - * Important integer-valued distributions: The Poisson distribution. Addison Wesley. - * The Poisson process (and hence, the returned value) is bounded by 1000 * mean. - * - For large means, we use the rejection algorithm described in - * Devroye, Luc. (1981). The Computer Generation of Poisson Random Variables Computing vol. 26 pp. 197-207. - * - * Based on Commons RNG implementation. - * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/PoissonSampler.html]. - */ -public class PoissonSampler private constructor(mean: Double) : Sampler { - private val poissonSamplerDelegate: Sampler = of(mean) - public override fun sample(generator: RandomGenerator): Chain = poissonSamplerDelegate.sample(generator) - public override fun toString(): String = poissonSamplerDelegate.toString() - - public companion object { - private const val PIVOT = 40.0 - - public fun of(mean: Double): Sampler =// Each sampler should check the input arguments. - if (mean < PIVOT) SmallMeanPoissonSampler.of(mean) else LargeMeanPoissonSampler.of(mean) - } -} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt deleted file mode 100644 index 0fe7ff161..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/SmallMeanPoissonSampler.kt +++ /dev/null @@ -1,50 +0,0 @@ -package space.kscience.kmath.stat.samplers - -import space.kscience.kmath.chains.Chain -import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler -import space.kscience.kmath.stat.chain -import kotlin.math.ceil -import kotlin.math.exp - -/** - * Sampler for the Poisson distribution. - * - For small means, a Poisson process is simulated using uniform deviates, as described in - * Knuth (1969). Seminumerical Algorithms. The Art of Computer Programming, Volume 2. Chapter 3.4.1.F.3 Important - * integer-valued distributions: The Poisson distribution. Addison Wesley. - * - The Poisson process (and hence, the returned value) is bounded by 1000 * mean. - * This sampler is suitable for mean < 40. For large means, [LargeMeanPoissonSampler] should be used instead. - * - * Based on Commons RNG implementation. - * - * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/SmallMeanPoissonSampler.html]. - */ -public class SmallMeanPoissonSampler private constructor(mean: Double) : Sampler { - private val p0: Double = exp(-mean) - - private val limit: Int = (if (p0 > 0) - ceil(1000 * mean) - else - throw IllegalArgumentException("No p(x=0) probability for mean: $mean")).toInt() - - public override fun sample(generator: RandomGenerator): Chain = generator.chain { - var n = 0 - var r = 1.0 - - while (n < limit) { - r *= nextDouble() - if (r >= p0) n++ else break - } - - n - } - - public override fun toString(): String = "Small Mean Poisson deviate" - - public companion object { - public fun of(mean: Double): SmallMeanPoissonSampler { - require(mean > 0) { "mean is not strictly positive: $mean" } - return SmallMeanPoissonSampler(mean) - } - } -} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt deleted file mode 100644 index 90815209f..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/samplers/ZigguratNormalizedGaussianSampler.kt +++ /dev/null @@ -1,88 +0,0 @@ -package space.kscience.kmath.stat.samplers - -import space.kscience.kmath.chains.Chain -import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler -import space.kscience.kmath.stat.chain -import kotlin.math.* - -/** - * [Marsaglia and Tsang "Ziggurat"](https://en.wikipedia.org/wiki/Ziggurat_algorithm) method for sampling from a - * Gaussian distribution with mean 0 and standard deviation 1. The algorithm is explained in this paper and this - * implementation has been adapted from the C code provided therein. - * - * Based on Commons RNG implementation. - * See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/ZigguratNormalizedGaussianSampler.html]. - */ -public class ZigguratNormalizedGaussianSampler private constructor() : - NormalizedGaussianSampler, Sampler { - - private fun sampleOne(generator: RandomGenerator): Double { - val j = generator.nextLong() - val i = (j and LAST.toLong()).toInt() - return if (abs(j) < K[i]) j * W[i] else fix(generator, j, i) - } - - public override fun sample(generator: RandomGenerator): Chain = generator.chain { sampleOne(this) } - public override fun toString(): String = "Ziggurat normalized Gaussian deviate" - - private fun fix(generator: RandomGenerator, hz: Long, iz: Int): Double { - var x = hz * W[iz] - - return when { - iz == 0 -> { - var y: Double - - do { - y = -ln(generator.nextDouble()) - x = -ln(generator.nextDouble()) * ONE_OVER_R - } while (y + y < x * x) - - val out = R + x - if (hz > 0) out else -out - } - - F[iz] + generator.nextDouble() * (F[iz - 1] - F[iz]) < gauss(x) -> x - else -> sampleOne(generator) - } - } - - public companion object { - private const val R: Double = 3.442619855899 - private const val ONE_OVER_R: Double = 1 / R - private const val V: Double = 9.91256303526217e-3 - private val MAX: Double = 2.0.pow(63.0) - private val ONE_OVER_MAX: Double = 1.0 / MAX - private const val LEN: Int = 128 - private const val LAST: Int = LEN - 1 - private val K: LongArray = LongArray(LEN) - private val W: DoubleArray = DoubleArray(LEN) - private val F: DoubleArray = DoubleArray(LEN) - - init { - // Filling the tables. - var d = R - var t = d - var fd = gauss(d) - val q = V / fd - K[0] = (d / q * MAX).toLong() - K[1] = 0 - W[0] = q * ONE_OVER_MAX - W[LAST] = d * ONE_OVER_MAX - F[0] = 1.0 - F[LAST] = fd - - (LAST - 1 downTo 1).forEach { i -> - d = sqrt(-2 * ln(V / d + fd)) - fd = gauss(d) - K[i + 1] = (d / t * MAX).toLong() - t = d - F[i] = fd - W[i] = d * ONE_OVER_MAX - } - } - - public fun of(): ZigguratNormalizedGaussianSampler = ZigguratNormalizedGaussianSampler() - private fun gauss(x: Double): Double = exp(-0.5 * x * x) - } -} diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt index 76aac65c4..c6b9cb17a 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -5,22 +5,23 @@ import kotlinx.coroutines.flow.toList import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test -import space.kscience.kmath.stat.samplers.GaussianSampler +import space.kscience.kmath.samplers.GaussianSampler +import space.kscience.kmath.structures.asBuffer internal class CommonsDistributionsTest { @Test - fun testNormalDistributionSuspend() { - val distribution = GaussianSampler.of(7.0, 2.0) + fun testNormalDistributionSuspend() = runBlocking { + val distribution = GaussianSampler(7.0, 2.0) val generator = RandomGenerator.default(1) - val sample = runBlocking { distribution.sample(generator).take(1000).toList() } - Assertions.assertEquals(7.0, sample.average(), 0.1) + val sample = distribution.sample(generator).take(1000).toList().asBuffer() + Assertions.assertEquals(7.0, Mean.double(sample), 0.2) } @Test - fun testNormalDistributionBlocking() { - val distribution = GaussianSampler.of(7.0, 2.0) + fun testNormalDistributionBlocking() = runBlocking { + val distribution = GaussianSampler(7.0, 2.0) val generator = RandomGenerator.default(1) - val sample = runBlocking { distribution.sample(generator).blocking().nextBlock(1000) } - Assertions.assertEquals(7.0, sample.average(), 0.1) + val sample = distribution.sample(generator).nextBufferBlocking(1000) + Assertions.assertEquals(7.0, Mean.double(sample), 0.2) } } diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt index 156e618f9..3c9d6a2e4 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt @@ -20,7 +20,7 @@ internal class StatisticTest { @Test fun testParallelMean() { runBlocking { - val average = Mean.real + val average = Mean.double .flow(chunked) //create a flow with results .drop(99) // Skip first 99 values and use one with total data .first() //get 1e5 data samples average From af4866e8763e48355e8d764a0c519a79feca78d0 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 1 Apr 2021 20:15:49 +0300 Subject: [PATCH 163/393] Refactor MST --- CHANGELOG.md | 4 + .../space/kscience/kmath/ast/expressions.kt | 10 +- .../kscience/kmath/ast/kotlingradSupport.kt | 12 +- .../kotlin/space/kscience/kmath/ast/MST.kt | 47 +++++- .../space/kscience/kmath/ast/MstExpression.kt | 138 ------------------ .../space/kscience/kmath/estree/estree.kt | 25 ++-- .../TestESTreeConsistencyWithInterpreter.kt | 82 ++++------- .../estree/TestESTreeOperationsSupport.kt | 15 +- .../kmath/estree/TestESTreeSpecialization.kt | 30 ++-- .../kmath/estree/TestESTreeVariables.kt | 7 +- .../kotlin/space/kscience/kmath/asm/asm.kt | 31 ++-- .../asm/TestAsmConsistencyWithInterpreter.kt | 82 ++++------- .../kmath/asm/TestAsmOperationsSupport.kt | 17 ++- .../kmath/asm/TestAsmSpecialization.kt | 30 ++-- .../kscience/kmath/asm/TestAsmVariables.kt | 7 +- .../space/kscience/kmath/ast/ParserTest.kt | 4 +- .../kotlingrad/DifferentiableMstExpression.kt | 49 +++---- .../kmath/kotlingrad/AdaptingTests.kt | 16 +- 18 files changed, 241 insertions(+), 365 deletions(-) delete mode 100644 kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ade9cd9c..c4d3b93e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - ScaleOperations interface - Field extends ScaleOperations - Basic integration API +- Basic MPP distributions and samplers ### Changed - Exponential operations merged with hyperbolic functions @@ -14,6 +15,8 @@ - NDStructure and NDAlgebra to StructureND and AlgebraND respectively - Real -> Double - DataSets are moved from functions to core +- Redesign advanced Chain API +- Redesign MST. Remove MSTExpression. ### Deprecated @@ -21,6 +24,7 @@ - Nearest in Domain. To be implemented in geometry package. - Number multiplication and division in main Algebra chain - `contentEquals` from Buffer. It moved to the companion. +- MSTExpression ### Fixed diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt index 17c85eea5..a4b8b7ca4 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt @@ -1,15 +1,17 @@ package space.kscience.kmath.ast -import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke fun main() { - val expr = DoubleField.mstInField { - val x = bindSymbol("x") + val expr = MstField { + val x = bindSymbol(x) x * 2.0 + number(2.0) / x - 16.0 } repeat(10000000) { - expr.invoke("x" to 1.0) + expr.interpret(DoubleField, x to 1.0) } } \ No newline at end of file diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt index 138b3e708..fb69177a2 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt @@ -1,9 +1,9 @@ package space.kscience.kmath.ast -import space.kscience.kmath.asm.compile +import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.expressions.derivative import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.kotlingrad.differentiable +import space.kscience.kmath.kotlingrad.toDiffExpression import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField @@ -14,11 +14,11 @@ import space.kscience.kmath.operations.DoubleField fun main() { val x by symbol - val actualDerivative = MstExpression(DoubleField, "x^2-4*x-44".parseMath()) - .differentiable() + val actualDerivative = "x^2-4*x-44".parseMath() + .toDiffExpression(DoubleField) .derivative(x) - .compile() - val expectedDerivative = MstExpression(DoubleField, "2*x-4".parseMath()).compile() + + val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField) assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0)) } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt index c459d7ff5..b8c2aadf7 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt @@ -1,5 +1,8 @@ package space.kscience.kmath.ast +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.misc.StringSymbol +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.NumericAlgebra @@ -76,11 +79,51 @@ public fun Algebra.evaluate(node: MST): T = when (node) { } } +internal class InnerAlgebra(val algebra: Algebra, val arguments: Map) : NumericAlgebra { + override fun bindSymbol(value: String): T = try { + algebra.bindSymbol(value) + } catch (ignored: IllegalStateException) { + null + } ?: arguments.getValue(StringSymbol(value)) + + override fun unaryOperation(operation: String, arg: T): T = + algebra.unaryOperation(operation, arg) + + override fun binaryOperation(operation: String, left: T, right: T): T = + algebra.binaryOperation(operation, left, right) + + override fun unaryOperationFunction(operation: String): (arg: T) -> T = + algebra.unaryOperationFunction(operation) + + override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = + algebra.binaryOperationFunction(operation) + + @Suppress("UNCHECKED_CAST") + override fun number(value: Number): T = if (algebra is NumericAlgebra<*>) + (algebra as NumericAlgebra).number(value) + else + error("Numeric nodes are not supported by $this") +} + /** - * Interprets the [MST] node with this [Algebra]. + * Interprets the [MST] node with this [Algebra] and optional [arguments] + */ +public fun MST.interpret(algebra: Algebra, arguments: Map): T = + InnerAlgebra(algebra, arguments).evaluate(this) + +/** + * Interprets the [MST] node with this [Algebra] and optional [arguments] * * @receiver the node to evaluate. * @param algebra the algebra that provides operations. * @return the value of expression. */ -public fun MST.interpret(algebra: Algebra): T = algebra.evaluate(this) +public fun MST.interpret(algebra: Algebra, vararg arguments: Pair): T = + interpret(algebra, mapOf(*arguments)) + +/** + * Interpret this [MST] as expression. + */ +public fun MST.toExpression(algebra: Algebra): Expression = Expression { arguments -> + interpret(algebra, arguments) +} diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt deleted file mode 100644 index 5c43df068..000000000 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt +++ /dev/null @@ -1,138 +0,0 @@ -package space.kscience.kmath.ast - -import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.StringSymbol -import space.kscience.kmath.misc.Symbol -import space.kscience.kmath.operations.* -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - -/** - * The expression evaluates MST on-flight. Should be much faster than functional expression, but slower than - * ASM-generated expressions. - * - * @property algebra the algebra that provides operations. - * @property mst the [MST] node. - * @author Alexander Nozik - */ -public class MstExpression>(public val algebra: A, public val mst: MST) : Expression { - private inner class InnerAlgebra(val arguments: Map) : NumericAlgebra { - override fun bindSymbol(value: String): T = try { - algebra.bindSymbol(value) - } catch (ignored: IllegalStateException) { - null - } ?: arguments.getValue(StringSymbol(value)) - - override fun unaryOperation(operation: String, arg: T): T = - algebra.unaryOperation(operation, arg) - - override fun binaryOperation(operation: String, left: T, right: T): T = - algebra.binaryOperation(operation, left, right) - - override fun unaryOperationFunction(operation: String): (arg: T) -> T = - algebra.unaryOperationFunction(operation) - - override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = - algebra.binaryOperationFunction(operation) - - @Suppress("UNCHECKED_CAST") - override fun number(value: Number): T = if (algebra is NumericAlgebra<*>) - (algebra as NumericAlgebra).number(value) - else - error("Numeric nodes are not supported by $this") - } - - override operator fun invoke(arguments: Map): T = InnerAlgebra(arguments).evaluate(mst) -} - -/** - * Builds [MstExpression] over [Algebra]. - * - * @author Alexander Nozik - */ -public inline fun , E : Algebra> A.mst( - mstAlgebra: E, - block: E.() -> MST, -): MstExpression = MstExpression(this, mstAlgebra.block()) - -/** - * Builds [MstExpression] over [Group]. - * - * @author Alexander Nozik - */ -public inline fun > A.mstInGroup(block: MstGroup.() -> MST): MstExpression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return MstExpression(this, MstGroup.block()) -} - -/** - * Builds [MstExpression] over [Ring]. - * - * @author Alexander Nozik - */ -public inline fun > A.mstInRing(block: MstRing.() -> MST): MstExpression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return MstExpression(this, MstRing.block()) -} - -/** - * Builds [MstExpression] over [Field]. - * - * @author Alexander Nozik - */ -public inline fun > A.mstInField(block: MstField.() -> MST): MstExpression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return MstExpression(this, MstField.block()) -} - -/** - * Builds [MstExpression] over [ExtendedField]. - * - * @author Iaroslav Postovalov - */ -public inline fun > A.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return MstExpression(this, MstExtendedField.block()) -} - -/** - * Builds [MstExpression] over [FunctionalExpressionGroup]. - * - * @author Alexander Nozik - */ -public inline fun > FunctionalExpressionGroup.mstInGroup(block: MstGroup.() -> MST): MstExpression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return algebra.mstInGroup(block) -} - -/** - * Builds [MstExpression] over [FunctionalExpressionRing]. - * - * @author Alexander Nozik - */ -public inline fun > FunctionalExpressionRing.mstInRing(block: MstRing.() -> MST): MstExpression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return algebra.mstInRing(block) -} - -/** - * Builds [MstExpression] over [FunctionalExpressionField]. - * - * @author Alexander Nozik - */ -public inline fun > FunctionalExpressionField.mstInField(block: MstField.() -> MST): MstExpression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return algebra.mstInField(block) -} - -/** - * Builds [MstExpression] over [FunctionalExpressionExtendedField]. - * - * @author Iaroslav Postovalov - */ -public inline fun > FunctionalExpressionExtendedField.mstInExtendedField( - block: MstExtendedField.() -> MST, -): MstExpression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return algebra.mstInExtendedField(block) -} diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt index 456a2ba07..93b2d54c8 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt @@ -2,10 +2,11 @@ package space.kscience.kmath.estree import space.kscience.kmath.ast.MST import space.kscience.kmath.ast.MST.* -import space.kscience.kmath.ast.MstExpression import space.kscience.kmath.estree.internal.ESTreeBuilder import space.kscience.kmath.estree.internal.estree.BaseExpression import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.NumericAlgebra @@ -64,19 +65,21 @@ internal fun MST.compileWith(algebra: Algebra): Expression { return ESTreeBuilder { visit(this@compileWith) }.instance } +/** + * Create a compiled expression with given [MST] and given [algebra]. + */ +public fun MST.compileToExpression(algebra: Algebra): Expression = compileWith(algebra) + /** - * Compiles an [MST] to ESTree generated expression using given algebra. - * - * @author Iaroslav Postovalov + * Compile given MST to expression and evaluate it against [arguments] */ -public fun Algebra.expression(mst: MST): Expression = - mst.compileWith(this) +public inline fun MST.compile(algebra: Algebra, arguments: Map): T = + compileToExpression(algebra).invoke(arguments) + /** - * Optimizes performance of an [MstExpression] by compiling it into ESTree generated expression. - * - * @author Iaroslav Postovalov + * Compile given MST to expression and evaluate it against [arguments] */ -public fun MstExpression>.compile(): Expression = - mst.compileWith(algebra) +public inline fun MST.compile(algebra: Algebra, vararg arguments: Pair): T = + compileToExpression(algebra).invoke(*arguments) diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt index 683c0337c..fb8d73c0c 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt @@ -3,16 +3,19 @@ package space.kscience.kmath.estree import space.kscience.kmath.ast.* import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.toComplex -import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals internal class TestESTreeConsistencyWithInterpreter { + @Test fun mstSpace() { - val res1 = MstGroup.mstInGroup { + + val mst = MstGroup { binaryOperationFunction("+")( unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (scale( @@ -23,27 +26,17 @@ internal class TestESTreeConsistencyWithInterpreter { number(1) ) + bindSymbol("x") + zero - }("x" to MST.Numeric(2)) + } - val res2 = MstGroup.mstInGroup { - binaryOperationFunction("+")( - unaryOperationFunction("+")( - number(3.toByte()) - (number(2.toByte()) + (scale( - add(number(1), number(1)), - 2.0 - ) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) - ), - - number(1) - ) + bindSymbol("x") + zero - }.compile()("x" to MST.Numeric(2)) - - assertEquals(res1, res2) + assertEquals( + mst.interpret(MstGroup, Symbol.x to MST.Numeric(2)), + mst.compile(MstGroup, Symbol.x to MST.Numeric(2)) + ) } @Test fun byteRing() { - val res1 = ByteRing.mstInRing { + val mst = MstRing { binaryOperationFunction("+")( unaryOperationFunction("+")( (bindSymbol("x") - (2.toByte() + (scale( @@ -54,62 +47,43 @@ internal class TestESTreeConsistencyWithInterpreter { number(1) ) * number(2) - }("x" to 3.toByte()) + } - val res2 = ByteRing.mstInRing { - binaryOperationFunction("+")( - unaryOperationFunction("+")( - (bindSymbol("x") - (2.toByte() + (scale( - add(number(1), number(1)), - 2.0 - ) + 1.toByte()))) * 3.0 - 1.toByte() - ), - number(1) - ) * number(2) - }.compile()("x" to 3.toByte()) - - assertEquals(res1, res2) + assertEquals( + mst.interpret(ByteRing, Symbol.x to 3.toByte()), + mst.compile(ByteRing, Symbol.x to 3.toByte()) + ) } @Test fun realField() { - val res1 = DoubleField.mstInField { + val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero - }("x" to 2.0) + } - val res2 = DoubleField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 - + number(1), - number(1) / 2 + number(2.0) * one - ) + zero - }.compile()("x" to 2.0) - - assertEquals(res1, res2) + assertEquals( + mst.interpret(DoubleField, Symbol.x to 2.0), + mst.compile(DoubleField, Symbol.x to 2.0) + ) } @Test fun complexField() { - val res1 = ComplexField.mstInField { + val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero - }("x" to 2.0.toComplex()) + } - val res2 = ComplexField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 - + number(1), - number(1) / 2 + number(2.0) * one - ) + zero - }.compile()("x" to 2.0.toComplex()) - - assertEquals(res1, res2) + assertEquals( + mst.interpret(ComplexField, Symbol.x to 2.0.toComplex()), + mst.compile(ComplexField, Symbol.x to 2.0.toComplex()) + ) } } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt index d59c048b6..24c003e3e 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt @@ -1,10 +1,9 @@ package space.kscience.kmath.estree -import space.kscience.kmath.ast.mstInExtendedField -import space.kscience.kmath.ast.mstInField -import space.kscience.kmath.ast.mstInGroup +import space.kscience.kmath.ast.MstExtendedField import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.invoke import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals @@ -12,29 +11,29 @@ import kotlin.test.assertEquals internal class TestESTreeOperationsSupport { @Test fun testUnaryOperationInvocation() { - val expression = DoubleField.mstInGroup { -bindSymbol("x") }.compile() + val expression = MstExtendedField { -bindSymbol("x") }.compileToExpression(DoubleField) val res = expression("x" to 2.0) assertEquals(-2.0, res) } @Test fun testBinaryOperationInvocation() { - val expression = DoubleField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile() + val expression = MstExtendedField { -bindSymbol("x") + number(1.0) }.compileToExpression(DoubleField) val res = expression("x" to 2.0) assertEquals(-1.0, res) } @Test fun testConstProductInvocation() { - val res = DoubleField.mstInField { bindSymbol("x") * 2 }("x" to 2.0) + val res = MstExtendedField { bindSymbol("x") * 2 }.compileToExpression(DoubleField)("x" to 2.0) assertEquals(4.0, res) } @Test fun testMultipleCalls() { val e = - DoubleField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } - .compile() + MstExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } + .compileToExpression(DoubleField) val r = Random(0) var s = 0.0 repeat(1000000) { s += e("x" to r.nextDouble()) } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt index 6be963175..c83fbc391 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt @@ -1,53 +1,63 @@ package space.kscience.kmath.estree -import space.kscience.kmath.ast.mstInField +import space.kscience.kmath.ast.MstExtendedField import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals internal class TestESTreeSpecialization { @Test fun testUnaryPlus() { - val expr = DoubleField.mstInField { unaryOperationFunction("+")(bindSymbol("x")) }.compile() + val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol("x")) }.compileToExpression(DoubleField) assertEquals(2.0, expr("x" to 2.0)) } @Test fun testUnaryMinus() { - val expr = DoubleField.mstInField { unaryOperationFunction("-")(bindSymbol("x")) }.compile() + val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol("x")) }.compileToExpression(DoubleField) assertEquals(-2.0, expr("x" to 2.0)) } @Test fun testAdd() { - val expr = DoubleField.mstInField { binaryOperationFunction("+")(bindSymbol("x"), bindSymbol("x")) }.compile() + val expr = MstExtendedField { + binaryOperationFunction("+")(bindSymbol("x"), + bindSymbol("x")) + }.compileToExpression(DoubleField) assertEquals(4.0, expr("x" to 2.0)) } @Test fun testSine() { - val expr = DoubleField.mstInField { unaryOperationFunction("sin")(bindSymbol("x")) }.compile() + val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol("x")) }.compileToExpression(DoubleField) assertEquals(0.0, expr("x" to 0.0)) } @Test fun testMinus() { - val expr = DoubleField.mstInField { binaryOperationFunction("-")(bindSymbol("x"), bindSymbol("x")) }.compile() + val expr = MstExtendedField { + binaryOperationFunction("-")(bindSymbol("x"), + bindSymbol("x")) + }.compileToExpression(DoubleField) assertEquals(0.0, expr("x" to 2.0)) } @Test fun testDivide() { - val expr = DoubleField.mstInField { binaryOperationFunction("/")(bindSymbol("x"), bindSymbol("x")) }.compile() + val expr = MstExtendedField { + binaryOperationFunction("/")(bindSymbol("x"), + bindSymbol("x")) + }.compileToExpression(DoubleField) assertEquals(1.0, expr("x" to 2.0)) } @Test fun testPower() { - val expr = DoubleField - .mstInField { binaryOperationFunction("pow")(bindSymbol("x"), number(2)) } - .compile() + val expr = MstExtendedField { + binaryOperationFunction("pow")(bindSymbol("x"), number(2)) + }.compileToExpression(DoubleField) assertEquals(4.0, expr("x" to 2.0)) } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt index ee8f4c6f5..0b1c1c33e 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt @@ -1,8 +1,9 @@ package space.kscience.kmath.estree -import space.kscience.kmath.ast.mstInRing +import space.kscience.kmath.ast.MstRing import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.ByteRing +import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith @@ -10,13 +11,13 @@ import kotlin.test.assertFailsWith internal class TestESTreeVariables { @Test fun testVariable() { - val expr = ByteRing.mstInRing { bindSymbol("x") }.compile() + val expr = MstRing{ bindSymbol("x") }.compileToExpression(ByteRing) assertEquals(1.toByte(), expr("x" to 1.toByte())) } @Test fun testUndefinedVariableFails() { - val expr = ByteRing.mstInRing { bindSymbol("x") }.compile() + val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing) assertFailsWith { expr() } } } diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt index 369fe136b..5324d74a1 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt @@ -4,8 +4,9 @@ import space.kscience.kmath.asm.internal.AsmBuilder import space.kscience.kmath.asm.internal.buildName import space.kscience.kmath.ast.MST import space.kscience.kmath.ast.MST.* -import space.kscience.kmath.ast.MstExpression import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.NumericAlgebra @@ -70,18 +71,22 @@ internal fun MST.compileWith(type: Class, algebra: Algebra): Exp return AsmBuilder(type, buildName(this)) { visit(this@compileWith) }.instance } -/** - * Compiles an [MST] to ASM using given algebra. - * - * @author Alexander Nozik - */ -public inline fun Algebra.expression(mst: MST): Expression = - mst.compileWith(T::class.java, this) /** - * Optimizes performance of an [MstExpression] using ASM codegen. - * - * @author Alexander Nozik + * Create a compiled expression with given [MST] and given [algebra]. */ -public inline fun MstExpression>.compile(): Expression = - mst.compileWith(T::class.java, algebra) +public inline fun MST.compileToExpression(algebra: Algebra): Expression = + compileWith(T::class.java, algebra) + + +/** + * Compile given MST to expression and evaluate it against [arguments] + */ +public inline fun MST.compile(algebra: Algebra, arguments: Map): T = + compileToExpression(algebra).invoke(arguments) + +/** + * Compile given MST to expression and evaluate it against [arguments] + */ +public inline fun MST.compile(algebra: Algebra, vararg arguments: Pair): T = + compileToExpression(algebra).invoke(*arguments) diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt index abc320360..096bf4447 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt @@ -3,16 +3,19 @@ package space.kscience.kmath.asm import space.kscience.kmath.ast.* import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.toComplex -import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals internal class TestAsmConsistencyWithInterpreter { + @Test fun mstSpace() { - val res1 = MstGroup.mstInGroup { + + val mst = MstGroup { binaryOperationFunction("+")( unaryOperationFunction("+")( number(3.toByte()) - (number(2.toByte()) + (scale( @@ -23,27 +26,17 @@ internal class TestAsmConsistencyWithInterpreter { number(1) ) + bindSymbol("x") + zero - }("x" to MST.Numeric(2)) + } - val res2 = MstGroup.mstInGroup { - binaryOperationFunction("+")( - unaryOperationFunction("+")( - number(3.toByte()) - (number(2.toByte()) + (scale( - add(number(1), number(1)), - 2.0 - ) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) - ), - - number(1) - ) + bindSymbol("x") + zero - }.compile()("x" to MST.Numeric(2)) - - assertEquals(res1, res2) + assertEquals( + mst.interpret(MstGroup, x to MST.Numeric(2)), + mst.compile(MstGroup, x to MST.Numeric(2)) + ) } @Test fun byteRing() { - val res1 = ByteRing.mstInRing { + val mst = MstRing { binaryOperationFunction("+")( unaryOperationFunction("+")( (bindSymbol("x") - (2.toByte() + (scale( @@ -54,62 +47,43 @@ internal class TestAsmConsistencyWithInterpreter { number(1) ) * number(2) - }("x" to 3.toByte()) + } - val res2 = ByteRing.mstInRing { - binaryOperationFunction("+")( - unaryOperationFunction("+")( - (bindSymbol("x") - (2.toByte() + (scale( - add(number(1), number(1)), - 2.0 - ) + 1.toByte()))) * 3.0 - 1.toByte() - ), - number(1) - ) * number(2) - }.compile()("x" to 3.toByte()) - - assertEquals(res1, res2) + assertEquals( + mst.interpret(ByteRing, x to 3.toByte()), + mst.compile(ByteRing, x to 3.toByte()) + ) } @Test fun realField() { - val res1 = DoubleField.mstInField { + val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero - }("x" to 2.0) + } - val res2 = DoubleField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 - + number(1), - number(1) / 2 + number(2.0) * one - ) + zero - }.compile()("x" to 2.0) - - assertEquals(res1, res2) + assertEquals( + mst.interpret(DoubleField, x to 2.0), + mst.compile(DoubleField, x to 2.0) + ) } @Test fun complexField() { - val res1 = ComplexField.mstInField { + val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero - }("x" to 2.0.toComplex()) + } - val res2 = ComplexField.mstInField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 - + number(1), - number(1) / 2 + number(2.0) * one - ) + zero - }.compile()("x" to 2.0.toComplex()) - - assertEquals(res1, res2) + assertEquals( + mst.interpret(ComplexField, x to 2.0.toComplex()), + mst.compile(ComplexField, x to 2.0.toComplex()) + ) } } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt index 5d70cb76b..d1a216ede 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt @@ -1,10 +1,11 @@ package space.kscience.kmath.asm -import space.kscience.kmath.ast.mstInExtendedField -import space.kscience.kmath.ast.mstInField -import space.kscience.kmath.ast.mstInGroup +import space.kscience.kmath.ast.MstExtendedField +import space.kscience.kmath.ast.MstField +import space.kscience.kmath.ast.MstGroup import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.invoke import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals @@ -12,29 +13,29 @@ import kotlin.test.assertEquals internal class TestAsmOperationsSupport { @Test fun testUnaryOperationInvocation() { - val expression = DoubleField.mstInGroup { -bindSymbol("x") }.compile() + val expression = MstGroup { -bindSymbol("x") }.compileToExpression(DoubleField) val res = expression("x" to 2.0) assertEquals(-2.0, res) } @Test fun testBinaryOperationInvocation() { - val expression = DoubleField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile() + val expression = MstGroup { -bindSymbol("x") + number(1.0) }.compileToExpression(DoubleField) val res = expression("x" to 2.0) assertEquals(-1.0, res) } @Test fun testConstProductInvocation() { - val res = DoubleField.mstInField { bindSymbol("x") * 2 }("x" to 2.0) + val res = MstField { bindSymbol("x") * 2 }.compileToExpression(DoubleField)("x" to 2.0) assertEquals(4.0, res) } @Test fun testMultipleCalls() { val e = - DoubleField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } - .compile() + MstExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } + .compileToExpression(DoubleField) val r = Random(0) var s = 0.0 repeat(1000000) { s += e("x" to r.nextDouble()) } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt index f485260c9..75a3ffaee 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt @@ -1,53 +1,63 @@ package space.kscience.kmath.asm -import space.kscience.kmath.ast.mstInField +import space.kscience.kmath.ast.MstExtendedField import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals internal class TestAsmSpecialization { @Test fun testUnaryPlus() { - val expr = DoubleField.mstInField { unaryOperationFunction("+")(bindSymbol("x")) }.compile() + val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol("x")) }.compileToExpression(DoubleField) assertEquals(2.0, expr("x" to 2.0)) } @Test fun testUnaryMinus() { - val expr = DoubleField.mstInField { unaryOperationFunction("-")(bindSymbol("x")) }.compile() + val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol("x")) }.compileToExpression(DoubleField) assertEquals(-2.0, expr("x" to 2.0)) } @Test fun testAdd() { - val expr = DoubleField.mstInField { binaryOperationFunction("+")(bindSymbol("x"), bindSymbol("x")) }.compile() + val expr = MstExtendedField { + binaryOperationFunction("+")(bindSymbol("x"), + bindSymbol("x")) + }.compileToExpression(DoubleField) assertEquals(4.0, expr("x" to 2.0)) } @Test fun testSine() { - val expr = DoubleField.mstInField { unaryOperationFunction("sin")(bindSymbol("x")) }.compile() + val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol("x")) }.compileToExpression(DoubleField) assertEquals(0.0, expr("x" to 0.0)) } @Test fun testMinus() { - val expr = DoubleField.mstInField { binaryOperationFunction("-")(bindSymbol("x"), bindSymbol("x")) }.compile() + val expr = MstExtendedField { + binaryOperationFunction("-")(bindSymbol("x"), + bindSymbol("x")) + }.compileToExpression(DoubleField) assertEquals(0.0, expr("x" to 2.0)) } @Test fun testDivide() { - val expr = DoubleField.mstInField { binaryOperationFunction("/")(bindSymbol("x"), bindSymbol("x")) }.compile() + val expr = MstExtendedField { + binaryOperationFunction("/")(bindSymbol("x"), + bindSymbol("x")) + }.compileToExpression(DoubleField) assertEquals(1.0, expr("x" to 2.0)) } @Test fun testPower() { - val expr = DoubleField - .mstInField { binaryOperationFunction("pow")(bindSymbol("x"), number(2)) } - .compile() + val expr = MstExtendedField { + binaryOperationFunction("pow")(bindSymbol("x"), number(2)) + }.compileToExpression(DoubleField) assertEquals(4.0, expr("x" to 2.0)) } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt index d1aaefffe..144d63eea 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt @@ -1,8 +1,9 @@ package space.kscience.kmath.asm -import space.kscience.kmath.ast.mstInRing +import space.kscience.kmath.ast.MstRing import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.ByteRing +import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith @@ -10,13 +11,13 @@ import kotlin.test.assertFailsWith internal class TestAsmVariables { @Test fun testVariable() { - val expr = ByteRing.mstInRing { bindSymbol("x") }.compile() + val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing) assertEquals(1.toByte(), expr("x" to 1.toByte())) } @Test fun testUndefinedVariableFails() { - val expr = ByteRing.mstInRing { bindSymbol("x") }.compile() + val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing) assertFailsWith { expr() } } } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt index 3d5449043..74f5e7e10 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt @@ -2,9 +2,9 @@ package space.kscience.kmath.ast import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.ComplexField -import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals @@ -18,7 +18,7 @@ internal class ParserTest { @Test fun `evaluate MSTExpression`() { - val res = ComplexField.mstInField { number(2) + number(2) * (number(2) + number(2)) }() + val res = MstField.invoke { number(2) + number(2) * (number(2) + number(2)) }.interpret(ComplexField) assertEquals(Complex(10.0, 0.0), res) } diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt index 1275b0c90..d5b55e031 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -3,8 +3,9 @@ package space.kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.api.SFun import space.kscience.kmath.ast.MST import space.kscience.kmath.ast.MstAlgebra -import space.kscience.kmath.ast.MstExpression +import space.kscience.kmath.ast.interpret import space.kscience.kmath.expressions.DifferentiableExpression +import space.kscience.kmath.expressions.Expression import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.NumericAlgebra @@ -18,38 +19,26 @@ import space.kscience.kmath.operations.NumericAlgebra * @param A the [NumericAlgebra] of [T]. * @property expr the underlying [MstExpression]. */ -public inline class DifferentiableMstExpression( - public val expr: MstExpression, -) : DifferentiableExpression> where A : NumericAlgebra { +public class DifferentiableMstExpression>( + public val algebra: A, + public val mst: MST, +) : DifferentiableExpression> { - public constructor(algebra: A, mst: MST) : this(MstExpression(algebra, mst)) + public override fun invoke(arguments: Map): T = mst.interpret(algebra, arguments) - /** - * The [MstExpression.algebra] of [expr]. - */ - public val algebra: A - get() = expr.algebra - - /** - * The [MstExpression.mst] of [expr]. - */ - public val mst: MST - get() = expr.mst - - public override fun invoke(arguments: Map): T = expr(arguments) - - public override fun derivativeOrNull(symbols: List): MstExpression = MstExpression( - algebra, - symbols.map(Symbol::identity) - .map(MstAlgebra::bindSymbol) - .map { it.toSVar>() } - .fold(mst.toSFun(), SFun>::d) - .toMst(), - ) + public override fun derivativeOrNull(symbols: List): DifferentiableMstExpression = + DifferentiableMstExpression( + algebra, + symbols.map(Symbol::identity) + .map(MstAlgebra::bindSymbol) + .map { it.toSVar>() } + .fold(mst.toSFun(), SFun>::d) + .toMst(), + ) } /** - * Wraps this [MstExpression] into [DifferentiableMstExpression]. + * Wraps this [MST] into [DifferentiableMstExpression]. */ -public fun > MstExpression.differentiable(): DifferentiableMstExpression = - DifferentiableMstExpression(this) +public fun > MST.toDiffExpression(algebra: A): DifferentiableMstExpression = + DifferentiableMstExpression(algebra, this) diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index 7cd3276b8..c4c25d789 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -1,9 +1,8 @@ package space.kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.api.* -import space.kscience.kmath.asm.compile +import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.ast.MstAlgebra -import space.kscience.kmath.ast.MstExpression import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.DoubleField @@ -43,8 +42,8 @@ internal class AdaptingTests { fun simpleFunctionDerivative() { val x = MstAlgebra.bindSymbol("x").toSVar>() val quadratic = "x^2-4*x-44".parseMath().toSFun>() - val actualDerivative = MstExpression(DoubleField, quadratic.d(x).toMst()).compile() - val expectedDerivative = MstExpression(DoubleField, "2*x-4".parseMath()).compile() + val actualDerivative = quadratic.d(x).toMst().compileToExpression(DoubleField) + val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField) assertEquals(actualDerivative("x" to 123.0), expectedDerivative("x" to 123.0)) } @@ -52,12 +51,11 @@ internal class AdaptingTests { fun moreComplexDerivative() { val x = MstAlgebra.bindSymbol("x").toSVar>() val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun>() - val actualDerivative = MstExpression(DoubleField, composition.d(x).toMst()).compile() + val actualDerivative = composition.d(x).toMst().compileToExpression(DoubleField) + + val expectedDerivative = + "-(2*x*cos(x^2)+2*sin(x)*cos(x)-16)/(2*sqrt(sin(x^2)-16*x-cos(x)^2))".parseMath().compileToExpression(DoubleField) - val expectedDerivative = MstExpression( - DoubleField, - "-(2*x*cos(x^2)+2*sin(x)*cos(x)-16)/(2*sqrt(sin(x^2)-16*x-cos(x)^2))".parseMath() - ).compile() assertEquals(actualDerivative("x" to 0.1), expectedDerivative("x" to 0.1)) } From 3e98240b94b99170ffd8525d9b307ac6c715ebd6 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 1 Apr 2021 20:21:14 +0300 Subject: [PATCH 164/393] add function diagonalEmbedding with tests --- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 42 ++++++++++++++++++- .../tensors/core/TestDoubleTensorAlgebra.kt | 33 +++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 323ade45d..ab692c0f9 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -283,7 +283,47 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra n || dim2 > n) { + throw RuntimeException("Dimension out of range") + } + + var lessDim = dim1 + var greaterDim = dim2 + var realOffset = offset + if (lessDim > greaterDim) { + realOffset *= -1 + lessDim = greaterDim.also {greaterDim = lessDim} + } + + val resShape = diagonalEntries.shape.slice(0 until lessDim).toIntArray() + + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + + diagonalEntries.shape.slice(lessDim until greaterDim - 1).toIntArray() + + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + + diagonalEntries.shape.slice(greaterDim - 1 until n - 1).toIntArray() + val resTensor = zeros(resShape) + + for (i in 0 until diagonalEntries.linearStructure.size) { + val multiIndex = diagonalEntries.linearStructure.index(i) + + var offset1 = 0 + var offset2 = abs(realOffset) + if (realOffset < 0) { + offset1 = offset2.also {offset2 = offset1} + } + val diagonalMultiIndex = multiIndex.slice(0 until lessDim).toIntArray() + + intArrayOf(multiIndex[n - 1] + offset1) + + multiIndex.slice(lessDim until greaterDim - 1).toIntArray() + + intArrayOf(multiIndex[n - 1] + offset2) + + multiIndex.slice(greaterDim - 1 until n - 1).toIntArray() + + resTensor[diagonalMultiIndex] = diagonalEntries[multiIndex] + } + + return resTensor } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 168d80a9d..692db69af 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -115,6 +115,39 @@ class TestDoubleTensorAlgebra { assertTrue(tensor4.dot(tensor5).shape contentEquals intArrayOf(5, 4, 2, 8, 3, 8, 5)) } + @Test + fun diagonalEmbedding() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) + val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor3 = zeros(intArrayOf(2, 3, 4, 5)) + + assertTrue(diagonalEmbedding(tensor3, 0, 3, 4).shape contentEquals + intArrayOf(2, 3, 4, 5, 5)) + assertTrue(diagonalEmbedding(tensor3, 1, 3, 4).shape contentEquals + intArrayOf(2, 3, 4, 6, 6)) + assertTrue(diagonalEmbedding(tensor3, 2, 0, 3).shape contentEquals + intArrayOf(7, 2, 3, 7, 4)) + + val diagonal1 = diagonalEmbedding(tensor1, 0, 1, 0) + assertTrue(diagonal1.shape contentEquals intArrayOf(3, 3)) + assertTrue(diagonal1.buffer.array() contentEquals + doubleArrayOf(10.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 30.0)) + + val diagonal1_offset = diagonalEmbedding(tensor1, 1, 1, 0) + assertTrue(diagonal1_offset.shape contentEquals intArrayOf(4, 4)) + assertTrue(diagonal1_offset.buffer.array() contentEquals + doubleArrayOf(0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 30.0, 0.0)) + + val diagonal2 = diagonalEmbedding(tensor2, 1, 0, 2) + assertTrue(diagonal2.shape contentEquals intArrayOf(4, 2, 4)) + assertTrue(diagonal2.buffer.array() contentEquals + doubleArrayOf( + 0.0, 1.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, + 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 5.0, 0.0, + 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 6.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) + } + @Test fun testContentEqual() = DoubleTensorAlgebra { //TODO() From a91d468b743c9a6df90bbd2cc3865aefd4241992 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 1 Apr 2021 21:27:30 +0300 Subject: [PATCH 165/393] Refactor Algebra and ExpressionAlgebra. Introduce bindSymbolOrNull on the top level --- .../ExpressionsInterpretersBenchmark.kt | 14 +++-- .../kmath/commons/fit/fitWithAutoDiff.kt | 4 +- .../kotlin/space/kscience/kmath/ast/MST.kt | 8 +-- .../space/kscience/kmath/ast/MstAlgebra.kt | 11 ++-- .../space/kscisnce/kmath/ast/InterpretTest.kt | 22 ++++++++ .../space/kscience/kmath/ast/ParserTest.kt | 2 +- .../DerivativeStructureExpression.kt | 10 ++-- .../DerivativeStructureExpressionTest.kt | 2 +- .../commons/optimization/OptimizeTest.kt | 5 +- .../space/kscience/kmath/complex/Complex.kt | 3 +- .../kscience/kmath/complex/Quaternion.kt | 4 +- .../complex/ExpressionFieldForComplexTest.kt | 2 +- kmath-core/api/kmath-core.api | 56 ++++++++++++++++--- .../kscience/kmath/expressions/Expression.kt | 17 +----- .../FunctionalExpressionAlgebra.kt | 9 ++- .../kmath/expressions/SimpleAutoDiff.kt | 2 +- .../kscience/kmath/operations/Algebra.kt | 14 ++++- .../kmath/expressions/SimpleAutoDiffTest.kt | 1 + kmath-viktor/api/kmath-viktor.api | 2 + 19 files changed, 123 insertions(+), 65 deletions(-) create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index 2438e3979..ad2a57597 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -4,14 +4,16 @@ import kotlinx.benchmark.Benchmark import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State -import space.kscience.kmath.asm.compile -import space.kscience.kmath.ast.mstInField +import space.kscience.kmath.asm.compileToExpression +import space.kscience.kmath.ast.MstField +import space.kscience.kmath.ast.toExpression import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.expressionInField import space.kscience.kmath.expressions.invoke import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke import kotlin.random.Random @State(Scope.Benchmark) @@ -28,20 +30,20 @@ internal class ExpressionsInterpretersBenchmark { @Benchmark fun mstExpression(blackhole: Blackhole) { - val expr = algebra.mstInField { + val expr = MstField { val x = bindSymbol(x) x * 2.0 + number(2.0) / x - 16.0 - } + }.toExpression(algebra) invokeAndSum(expr, blackhole) } @Benchmark fun asmExpression(blackhole: Blackhole) { - val expr = algebra.mstInField { + val expr = MstField { val x = bindSymbol(x) x * 2.0 + number(2.0) / x - 16.0 - }.compile() + }.compileToExpression(algebra) invokeAndSum(expr, blackhole) } diff --git a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt index 02534ac98..813310680 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -62,8 +62,8 @@ suspend fun main() { // compute differentiable chi^2 sum for given model ax^2 + bx + c val chi2 = FunctionOptimization.chiSquared(x, y, yErr) { x1 -> //bind variables to autodiff context - val a = bind(a) - val b = bind(b) + val a = bindSymbol(a) + val b = bindSymbol(b) //Include default value for c if it is not provided as a parameter val c = bindSymbolOrNull(c) ?: one a * x1.pow(2) + b * x1 + c diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt index b8c2aadf7..4c37b09f4 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt @@ -58,7 +58,7 @@ public fun Algebra.evaluate(node: MST): T = when (node) { is MST.Numeric -> (this as? NumericAlgebra)?.number(node.value) ?: error("Numeric nodes are not supported by $this") - is MST.Symbolic -> bindSymbol(node.value) + is MST.Symbolic -> bindSymbol(node.value) ?: error("Symbol '${node.value}' is not supported in $this") is MST.Unary -> when { this is NumericAlgebra && node.value is MST.Numeric -> unaryOperationFunction(node.operation)(number(node.value.value)) @@ -80,11 +80,7 @@ public fun Algebra.evaluate(node: MST): T = when (node) { } internal class InnerAlgebra(val algebra: Algebra, val arguments: Map) : NumericAlgebra { - override fun bindSymbol(value: String): T = try { - algebra.bindSymbol(value) - } catch (ignored: IllegalStateException) { - null - } ?: arguments.getValue(StringSymbol(value)) + override fun bindSymbolOrNull(value: String): T? = algebra.bindSymbolOrNull(value) ?: arguments[StringSymbol(value)] override fun unaryOperation(operation: String, arg: T): T = algebra.unaryOperation(operation, arg) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt index c1aeae90e..edac0f9bd 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt @@ -8,7 +8,8 @@ import space.kscience.kmath.operations.* */ public object MstAlgebra : NumericAlgebra { public override fun number(value: Number): MST.Numeric = MST.Numeric(value) - public override fun bindSymbol(value: String): MST.Symbolic = MST.Symbolic(value) + public override fun bindSymbolOrNull(value: String): MST.Symbolic = MST.Symbolic(value) + override fun bindSymbol(value: String): MST.Symbolic = bindSymbolOrNull(value) public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = { arg -> MST.Unary(operation, arg) } @@ -24,7 +25,7 @@ public object MstGroup : Group, NumericAlgebra, ScaleOperations { public override val zero: MST.Numeric = number(0.0) public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) - public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value) + public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value) public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(GroupOperations.PLUS_OPERATION)(a, b) public override operator fun MST.unaryPlus(): MST.Unary = unaryOperationFunction(GroupOperations.PLUS_OPERATION)(this) @@ -54,7 +55,7 @@ public object MstRing : Ring, NumbersAddOperations, ScaleOperations, NumbersAddOperations, ScaleOperations< public override val one: MST.Numeric get() = MstRing.one - public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value) + public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value) public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b) @@ -112,7 +113,7 @@ public object MstExtendedField : ExtendedField, NumericAlgebra { public override val zero: MST.Numeric get() = MstField.zero public override val one: MST.Numeric get() = MstField.one - public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value) + public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value) public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg) public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg) diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt new file mode 100644 index 000000000..1b8ec1490 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt @@ -0,0 +1,22 @@ +package space.kscisnce.kmath.ast + +import space.kscience.kmath.ast.MstField +import space.kscience.kmath.ast.toExpression +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.Symbol.Companion.x +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test + +class InterpretTest { + + @Test + fun interpretation(){ + val expr = MstField { + val x = bindSymbol(x) + x * 2.0 + number(2.0) / x - 16.0 + }.toExpression(DoubleField) + expr(x to 2.2) + } +} \ No newline at end of file diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt index 74f5e7e10..2b83e566e 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt @@ -40,7 +40,7 @@ internal class ParserTest { @Test fun `evaluate MST with binary function`() { val magicalAlgebra = object : Algebra { - override fun bindSymbol(value: String): String = value + override fun bindSymbolOrNull(value: String): String = value override fun unaryOperationFunction(operation: String): (arg: String) -> String { throw NotImplementedError() diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 58e9687e5..76f6c6ff5 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -2,7 +2,6 @@ package space.kscience.kmath.commons.expressions import org.apache.commons.math3.analysis.differentiation.DerivativeStructure import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.StringSymbol import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.ExtendedField @@ -51,11 +50,11 @@ public class DerivativeStructureField( override fun const(value: Double): DerivativeStructure = DerivativeStructure(numberOfVariables, order, value) - public override fun bindSymbolOrNull(symbol: Symbol): DerivativeStructureSymbol? = variables[symbol.identity] + override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol? = variables[value] + override fun bindSymbol(value: String): DerivativeStructureSymbol = variables.getValue(value) - public fun bind(symbol: Symbol): DerivativeStructureSymbol = variables.getValue(symbol.identity) - - override fun bindSymbol(value: String): DerivativeStructureSymbol = bind(StringSymbol(value)) + public fun bindSymbolOrNull(symbol: Symbol): DerivativeStructureSymbol? = variables[symbol.identity] + public fun bindSymbol(symbol: Symbol): DerivativeStructureSymbol = variables.getValue(symbol.identity) public fun DerivativeStructure.derivative(symbols: List): Double { require(symbols.size <= order) { "The order of derivative ${symbols.size} exceeds computed order $order" } @@ -108,7 +107,6 @@ public class DerivativeStructureField( } } - /** * A constructs that creates a derivative structure with required order on-demand */ diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt index b19eb5950..ad0c0b7eb 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt @@ -27,7 +27,7 @@ internal class AutoDiffTest { @Test fun derivativeStructureFieldTest() { diff(2, x to 1.0, y to 1.0) { - val x = bind(x)//by binding() + val x = bindSymbol(x)//by binding() val y = bindSymbol("y") val z = x * (-sin(x * y) + y) + 2.0 println(z.derivative(x)) diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt index a51c407c2..de22c066b 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -14,7 +14,8 @@ internal class OptimizeTest { val y by symbol val normal = DerivativeStructureExpression { - exp(-bind(x).pow(2) / 2) + exp(-bind(y).pow(2) / 2) + exp(-bindSymbol(x).pow(2) / 2) + exp(-bindSymbol(y) + .pow(2) / 2) } @Test @@ -58,7 +59,7 @@ internal class OptimizeTest { val chi2 = FunctionOptimization.chiSquared(x, y, yErr) { x1 -> val cWithDefault = bindSymbolOrNull(c) ?: one - bind(a) * x1.pow(2) + bind(b) * x1 + cWithDefault + bindSymbol(a) * x1.pow(2) + bindSymbol(b) * x1 + cWithDefault } val result = chi2.minimize(a to 1.5, b to 0.9, c to 1.0) diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt index a73fb0201..e98b41b9b 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt @@ -165,8 +165,7 @@ public object ComplexField : ExtendedField, Norm, Num public override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg) - public override fun bindSymbol(value: String): Complex = - if (value == "i") i else super.bindSymbol(value) + public override fun bindSymbolOrNull(value: String): Complex? = if (value == "i") i else null } /** diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index 9a0346ca7..a8189dfe8 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -165,11 +165,11 @@ public object QuaternionField : Field, Norm, public override fun Quaternion.unaryMinus(): Quaternion = Quaternion(-w, -x, -y, -z) public override fun norm(arg: Quaternion): Quaternion = sqrt(arg.conjugate * arg) - public override fun bindSymbol(value: String): Quaternion = when (value) { + public override fun bindSymbolOrNull(value: String): Quaternion? = when (value) { "i" -> i "j" -> j "k" -> k - else -> super.bindSymbol(value) + else -> null } override fun number(value: Number): Quaternion = value.toQuaternion() diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt index 3837b0d40..c08e73800 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt @@ -1,9 +1,9 @@ package space.kscience.kmath.complex import space.kscience.kmath.expressions.FunctionalExpressionField -import space.kscience.kmath.expressions.bindSymbol import space.kscience.kmath.expressions.invoke import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.bindSymbol import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index e6f4697aa..f4724a50e 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -50,8 +50,6 @@ public abstract interface class space/kscience/kmath/expressions/Expression { } public abstract interface class space/kscience/kmath/expressions/ExpressionAlgebra : space/kscience/kmath/operations/Algebra { - public abstract fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public abstract fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; public abstract fun const (Ljava/lang/Object;)Ljava/lang/Object; } @@ -59,6 +57,7 @@ public final class space/kscience/kmath/expressions/ExpressionAlgebra$DefaultImp public static fun binaryOperation (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Ljava/lang/String;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperationFunction (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -71,7 +70,6 @@ public final class space/kscience/kmath/expressions/ExpressionBuildersKt { } public final class space/kscience/kmath/expressions/ExpressionKt { - public static final fun bindSymbol (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; public static final fun binding (Lspace/kscience/kmath/expressions/ExpressionAlgebra;)Lkotlin/properties/ReadOnlyProperty; public static final fun callByString (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object; public static final fun callBySymbol (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object; @@ -91,8 +89,8 @@ public abstract class space/kscience/kmath/expressions/FunctionalExpressionAlgeb public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; - public fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun const (Ljava/lang/Object;)Ljava/lang/Object; public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression; public final fun getAlgebra ()Lspace/kscience/kmath/operations/Algebra; @@ -278,8 +276,8 @@ public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscien public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public synthetic fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; - public fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/AutoDiffValue; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun const (Ljava/lang/Object;)Ljava/lang/Object; public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/AutoDiffValue; public final fun const (Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/AutoDiffValue; @@ -743,6 +741,8 @@ public class space/kscience/kmath/nd/BufferedGroupND : space/kscience/kmath/nd/B public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; @@ -890,6 +890,7 @@ public final class space/kscience/kmath/nd/FieldND$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; public static fun div (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public static fun div (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public static fun div (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; @@ -935,6 +936,7 @@ public final class space/kscience/kmath/nd/GroupND$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; public static fun invoke (Lspace/kscience/kmath/nd/GroupND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public static fun minus (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public static fun minus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; @@ -970,6 +972,7 @@ public final class space/kscience/kmath/nd/RingND$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; public static fun invoke (Lspace/kscience/kmath/nd/RingND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public static fun minus (Lspace/kscience/kmath/nd/RingND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public static fun minus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; @@ -1118,6 +1121,7 @@ public abstract interface class space/kscience/kmath/operations/Algebra { public abstract fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public abstract fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public abstract fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public abstract fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -1126,6 +1130,7 @@ public final class space/kscience/kmath/operations/Algebra$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/operations/Algebra;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Algebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Algebra;Ljava/lang/String;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/Algebra;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Algebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -1156,6 +1161,7 @@ public final class space/kscience/kmath/operations/AlgebraExtensionsKt { public final class space/kscience/kmath/operations/AlgebraKt { public static final fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; + public static final fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; public static final fun invoke (Lspace/kscience/kmath/operations/Algebra;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } @@ -1201,6 +1207,8 @@ public final class space/kscience/kmath/operations/BigIntField : space/kscience/ public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/operations/BigInt; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/operations/BigInt; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun div (Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt; @@ -1274,6 +1282,8 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Byte; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Byte; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun getOne ()Ljava/lang/Byte; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Byte; @@ -1326,6 +1336,8 @@ public final class space/kscience/kmath/operations/DoubleField : space/kscience/ public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Double; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Double; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun cos (D)Ljava/lang/Double; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cosh (D)Ljava/lang/Double; @@ -1426,6 +1438,7 @@ public final class space/kscience/kmath/operations/ExponentialOperations$Default public static fun binaryOperation (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -1447,6 +1460,7 @@ public final class space/kscience/kmath/operations/ExtendedField$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Ljava/lang/Object; public static fun cosh (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -1480,6 +1494,7 @@ public final class space/kscience/kmath/operations/ExtendedFieldOperations$Defau public static fun binaryOperation (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun minus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -1501,6 +1516,7 @@ public final class space/kscience/kmath/operations/Field$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; @@ -1534,6 +1550,7 @@ public final class space/kscience/kmath/operations/FieldOperations$DefaultImpls public static fun binaryOperation (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun minus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -1564,6 +1581,8 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Float; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Float; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun cos (F)Ljava/lang/Float; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cosh (F)Ljava/lang/Float; @@ -1637,6 +1656,7 @@ public final class space/kscience/kmath/operations/Group$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Ljava/lang/Object; public static fun minus (Lspace/kscience/kmath/operations/Group;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/Group;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; @@ -1666,6 +1686,7 @@ public final class space/kscience/kmath/operations/GroupOperations$DefaultImpls public static fun binaryOperation (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Ljava/lang/Object; public static fun minus (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; @@ -1682,6 +1703,8 @@ public final class space/kscience/kmath/operations/IntRing : space/kscience/kmat public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Integer; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Integer; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun getOne ()Ljava/lang/Integer; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Integer; @@ -1732,6 +1755,8 @@ public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : spa public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Ljava/math/BigDecimal; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/math/BigDecimal; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun div (Ljava/math/BigDecimal;Ljava/lang/Number;)Ljava/math/BigDecimal; @@ -1788,6 +1813,8 @@ public final class space/kscience/kmath/operations/JBigIntegerField : space/ksci public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Ljava/math/BigInteger; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/math/BigInteger; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Ljava/math/BigInteger; public synthetic fun getZero ()Ljava/lang/Object; @@ -1829,6 +1856,8 @@ public final class space/kscience/kmath/operations/LongRing : space/kscience/kma public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Long; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Long; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun getOne ()Ljava/lang/Long; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Long; @@ -1868,6 +1897,7 @@ public final class space/kscience/kmath/operations/NumbersAddOperations$DefaultI public static fun binaryOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Ljava/lang/Object; public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun minus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; @@ -1895,6 +1925,7 @@ public final class space/kscience/kmath/operations/NumericAlgebra$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;)Ljava/lang/Object; public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; @@ -1924,6 +1955,7 @@ public final class space/kscience/kmath/operations/PowerOperations$DefaultImpls public static fun binaryOperation (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;)Ljava/lang/Object; public static fun pow (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun sqrt (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; @@ -1938,6 +1970,7 @@ public final class space/kscience/kmath/operations/Ring$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Ljava/lang/Object; public static fun minus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun times (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -1962,6 +1995,7 @@ public final class space/kscience/kmath/operations/RingOperations$DefaultImpls { public static fun binaryOperation (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Ljava/lang/Object; public static fun minus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun plus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun times (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -1981,6 +2015,7 @@ public final class space/kscience/kmath/operations/ScaleOperations$DefaultImpls public static fun binaryOperation (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Ljava/lang/Object; public static fun div (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public static fun times (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public static fun times (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; @@ -1997,6 +2032,8 @@ public final class space/kscience/kmath/operations/ShortRing : space/kscience/km public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Short; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Short; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Ljava/lang/Short; public synthetic fun getZero ()Ljava/lang/Object; @@ -2057,6 +2094,7 @@ public final class space/kscience/kmath/operations/TrigonometricOperations$Defau public static fun binaryOperation (Lspace/kscience/kmath/operations/TrigonometricOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/TrigonometricOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public static fun bindSymbol (Lspace/kscience/kmath/operations/TrigonometricOperations;Ljava/lang/String;)Ljava/lang/Object; + public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/TrigonometricOperations;Ljava/lang/String;)Ljava/lang/Object; public static fun unaryOperation (Lspace/kscience/kmath/operations/TrigonometricOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/TrigonometricOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -2147,6 +2185,8 @@ public final class space/kscience/kmath/structures/DoubleBufferField : space/ksc public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cos-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; @@ -2232,6 +2272,8 @@ public final class space/kscience/kmath/structures/DoubleBufferFieldOperations : public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cos-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt index 7918f199e..fc49a0fae 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt @@ -55,15 +55,6 @@ public operator fun Expression.invoke(vararg pairs: Pair): T = * @param E type of the actual expression state */ public interface ExpressionAlgebra : Algebra { - /** - * Bind a given [Symbol] to this context variable and produce context-specific object. Return null if symbol could not be bound in current context. - */ - public fun bindSymbolOrNull(symbol: Symbol): E? - - /** - * Bind a string to a context using [StringSymbol] - */ - override fun bindSymbol(value: String): E = bindSymbol(StringSymbol(value)) /** * A constant expression which does not depend on arguments @@ -71,15 +62,9 @@ public interface ExpressionAlgebra : Algebra { public fun const(value: T): E } -/** - * Bind a given [Symbol] to this context variable and produce context-specific object. - */ -public fun ExpressionAlgebra.bindSymbol(symbol: Symbol): E = - bindSymbolOrNull(symbol) ?: error("Symbol $symbol could not be bound to $this") - /** * Bind a symbol by name inside the [ExpressionAlgebra] */ public fun ExpressionAlgebra.binding(): ReadOnlyProperty = ReadOnlyProperty { _, property -> - bindSymbol(StringSymbol(property.name)) ?: error("A variable with name ${property.name} does not exist") + bindSymbol(property.name) ?: error("A variable with name ${property.name} does not exist") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index ebd9e7f22..775a49aad 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.StringSymbol import space.kscience.kmath.operations.* /** @@ -19,8 +19,8 @@ public abstract class FunctionalExpressionAlgebra>( /** * Builds an Expression to access a variable. */ - public override fun bindSymbolOrNull(symbol: Symbol): Expression? = Expression { arguments -> - arguments[symbol] ?: error("Argument not found: $symbol") + override fun bindSymbolOrNull(value: String): Expression? = Expression { arguments -> + arguments[StringSymbol(value)] ?: error("Argument not found: $value") } /** @@ -101,8 +101,7 @@ public open class FunctionalExpressionRing>( public open class FunctionalExpressionField>( algebra: A, -) : FunctionalExpressionRing(algebra), Field>, - ScaleOperations> { +) : FunctionalExpressionRing(algebra), Field>, ScaleOperations> { /** * Builds an Expression of division an expression by another one. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt index d9be4a92e..d3b65107d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -85,7 +85,7 @@ public open class SimpleAutoDiffField>( override fun hashCode(): Int = identity.hashCode() } - public override fun bindSymbolOrNull(symbol: Symbol): AutoDiffValue? = bindings[symbol.identity] + override fun bindSymbolOrNull(value: String): AutoDiffValue? = bindings[value] private fun getDerivative(variable: AutoDiffValue): T = (variable as? AutoDiffVariableWithDerivative)?.d ?: derivatives[variable] ?: context.zero diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 492ec8e88..78ada6f5c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -23,10 +23,18 @@ public interface Algebra { * * In case if algebra can't parse the string, this method must throw [kotlin.IllegalStateException]. * + * Returns `null` if symbol could not be bound to the context + * * @param value the raw string. * @return an object. */ - public fun bindSymbol(value: String): T = error("Wrapping of '$value' is not supported in $this") + public fun bindSymbolOrNull(value: String): T? = null + + /** + * The same as [bindSymbolOrNull] but throws an error if symbol could not be bound + */ + public fun bindSymbol(value: String): T = + bindSymbolOrNull(value) ?: error("Symbol '$value' is not supported in $this") /** * Dynamically dispatches an unary operation with the certain name. @@ -91,7 +99,9 @@ public interface Algebra { binaryOperationFunction(operation)(left, right) } -public fun Algebra.bindSymbol(symbol: Symbol): T = bindSymbol(symbol.identity) +public fun Algebra.bindSymbolOrNull(symbol: Symbol): T? = bindSymbolOrNull(symbol.identity) + +public fun Algebra.bindSymbol(symbol: Symbol): T = bindSymbol(symbol.identity) /** * Call a block with an [Algebra] as receiver. diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt index 666db13d8..0cac510d0 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -3,6 +3,7 @@ package space.kscience.kmath.expressions import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer import kotlin.math.E diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api index 0b9ea1b48..e209c863c 100644 --- a/kmath-viktor/api/kmath-viktor.api +++ b/kmath-viktor/api/kmath-viktor.api @@ -46,6 +46,8 @@ public final class space/kscience/kmath/viktor/ViktorFieldND : space/kscience/km public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public fun combine-WKhNzhk (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; From e6921025d11b20d8bd18d29242035ae4dbdb8455 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 2 Apr 2021 16:46:12 +0700 Subject: [PATCH 166/393] Remove redundant try-catch expressions --- .../src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt | 2 +- .../src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt | 6 +----- .../src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt | 6 +----- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt index 4c37b09f4..538db0caa 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt @@ -58,7 +58,7 @@ public fun Algebra.evaluate(node: MST): T = when (node) { is MST.Numeric -> (this as? NumericAlgebra)?.number(node.value) ?: error("Numeric nodes are not supported by $this") - is MST.Symbolic -> bindSymbol(node.value) ?: error("Symbol '${node.value}' is not supported in $this") + is MST.Symbolic -> bindSymbol(node.value) is MST.Unary -> when { this is NumericAlgebra && node.value is MST.Numeric -> unaryOperationFunction(node.operation)(number(node.value.value)) diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt index 93b2d54c8..796ffce1e 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt @@ -14,11 +14,7 @@ import space.kscience.kmath.operations.NumericAlgebra internal fun MST.compileWith(algebra: Algebra): Expression { fun ESTreeBuilder.visit(node: MST): BaseExpression = when (node) { is Symbolic -> { - val symbol = try { - algebra.bindSymbol(node.value) - } catch (ignored: IllegalStateException) { - null - } + val symbol = algebra.bindSymbolOrNull(node.value) if (symbol != null) constant(symbol) diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt index 5324d74a1..ee2b6fb54 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt @@ -22,11 +22,7 @@ import space.kscience.kmath.operations.NumericAlgebra internal fun MST.compileWith(type: Class, algebra: Algebra): Expression { fun AsmBuilder.visit(node: MST): Unit = when (node) { is Symbolic -> { - val symbol = try { - algebra.bindSymbol(node.value) - } catch (ignored: IllegalStateException) { - null - } + val symbol = algebra.bindSymbolOrNull(node.value) if (symbol != null) loadObjectConstant(symbol as Any) From f7e792faffe6d08c09d4d11f39be4265bb431256 Mon Sep 17 00:00:00 2001 From: darksnake Date: Fri, 2 Apr 2021 19:09:35 +0300 Subject: [PATCH 167/393] Add test for grid iteration. --- .../commonTest/kotlin/kaceince/kmath/real/GridTest.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt index 91ee517ab..a7c4d30e2 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt @@ -15,4 +15,13 @@ class GridTest { assertEquals(6, grid.size) assertTrue { (grid - DoubleVector(0.0, 0.2, 0.4, 0.6, 0.8, 1.0)).norm < 1e-4 } } + + @Test + fun testIterateGrid(){ + var res = 0.0 + for(d in 0.0..1.0 step 0.2){ + res = d + } + assertEquals(1.0, res) + } } \ No newline at end of file From cf91da1a988d6bbc507a9c86a463b43f1ecf6af2 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 31 Mar 2021 21:51:54 +0700 Subject: [PATCH 168/393] Add pi and e constants, some unrelated changes --- .../kmath/structures/StreamDoubleFieldND.kt | 12 ++--- .../space/kscience/kmath/ast/MstAlgebra.kt | 14 +++--- .../ast/rendering/LatexSyntaxRenderer.kt | 1 + .../ast/rendering/MathMLSyntaxRenderer.kt | 1 + .../kmath/ast/rendering/MathRenderer.kt | 5 +- .../kmath/ast/rendering/MathSyntax.kt | 5 ++ .../kscience/kmath/ast/rendering/features.kt | 19 +++++++ .../kmath/ast/rendering/TestFeatures.kt | 5 ++ .../kscience/kmath/ast/rendering/TestLatex.kt | 5 +- .../kmath/ast/rendering/TestMathML.kt | 5 +- .../DerivativeStructureExpression.kt | 18 +++---- .../space/kscience/kmath/complex/Complex.kt | 8 +-- .../kscience/kmath/complex/ComplexFieldND.kt | 36 +++++++------- kmath-core/api/kmath-core.api | 19 +++++++ .../FunctionalExpressionAlgebra.kt | 19 +++++-- .../kmath/expressions/SimpleAutoDiff.kt | 6 ++- .../space/kscience/kmath/nd/AlgebraND.kt | 12 ++--- .../space/kscience/kmath/nd/DoubleFieldND.kt | 49 +++++++++---------- .../kscience/kmath/operations/Algebra.kt | 12 ++--- .../kmath/operations/AlgebraElements.kt | 7 +-- .../kmath/operations/NumericAlgebra.kt | 28 +++++++++-- .../kscience/kmath/operations/numbers.kt | 48 +++++++++--------- .../kscience/kmath/stat/StatisticTest.kt | 1 - kmath-viktor/api/kmath-viktor.api | 2 +- .../kmath/viktor/ViktorStructureND.kt | 28 +++++------ 25 files changed, 225 insertions(+), 140 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt index 6741209fc..162c63df9 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -1,6 +1,5 @@ package space.kscience.kmath.structures -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExtendedField @@ -9,12 +8,10 @@ import java.util.* import java.util.stream.IntStream /** - * A demonstration implementation of NDField over Real using Java [DoubleStream] for parallel execution + * A demonstration implementation of NDField over Real using Java [java.util.stream.DoubleStream] for parallel + * execution. */ -@OptIn(UnstableKMathAPI::class) -class StreamDoubleFieldND( - override val shape: IntArray, -) : FieldND, +class StreamDoubleFieldND(override val shape: IntArray) : FieldND, NumbersAddOperations>, ExtendedField> { @@ -38,7 +35,6 @@ class StreamDoubleFieldND( else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) } } - override fun produce(initializer: DoubleField.(IntArray) -> Double): BufferND { val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset -> val index = strides.index(offset) @@ -104,4 +100,4 @@ class StreamDoubleFieldND( override fun atanh(arg: StructureND): BufferND = arg.map { atanh(it) } } -fun AlgebraND.Companion.realWithStream(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(shape) \ No newline at end of file +fun AlgebraND.Companion.realWithStream(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(shape) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt index edac0f9bd..33fca7521 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt @@ -49,9 +49,10 @@ public object MstGroup : Group, NumericAlgebra, ScaleOperations { /** * [Ring] over [MST] nodes. */ +@Suppress("OVERRIDE_BY_INLINE") @OptIn(UnstableKMathAPI::class) public object MstRing : Ring, NumbersAddOperations, ScaleOperations { - public override val zero: MST.Numeric get() = MstGroup.zero + public override inline val zero: MST.Numeric get() = MstGroup.zero public override val one: MST.Numeric = number(1.0) public override fun number(value: Number): MST.Numeric = MstGroup.number(value) @@ -78,11 +79,11 @@ public object MstRing : Ring, NumbersAddOperations, ScaleOperations, NumbersAddOperations, ScaleOperations { - public override val zero: MST.Numeric get() = MstRing.zero - - public override val one: MST.Numeric get() = MstRing.one + public override inline val zero: MST.Numeric get() = MstRing.zero + public override inline val one: MST.Numeric get() = MstRing.one public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value) @@ -109,9 +110,10 @@ public object MstField : Field, NumbersAddOperations, ScaleOperations< /** * [ExtendedField] over [MST] nodes. */ +@Suppress("OVERRIDE_BY_INLINE") public object MstExtendedField : ExtendedField, NumericAlgebra { - public override val zero: MST.Numeric get() = MstField.zero - public override val one: MST.Numeric get() = MstField.one + public override inline val zero: MST.Numeric get() = MstField.zero + public override inline val one: MST.Numeric get() = MstField.one public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt index 914da6d9f..5d40097b6 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -34,6 +34,7 @@ public object LatexSyntaxRenderer : SyntaxRenderer { is SpecialSymbolSyntax -> when (node.kind) { SpecialSymbolSyntax.Kind.INFINITY -> append("\\infty") + SpecialSymbolSyntax.Kind.SMALL_PI -> append("\\pi") } is OperandSyntax -> { diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index 6f194be86..d1d3c82e3 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -48,6 +48,7 @@ public object MathMLSyntaxRenderer : SyntaxRenderer { is SpecialSymbolSyntax -> when (node.kind) { SpecialSymbolSyntax.Kind.INFINITY -> tag("mo") { append("∞") } + SpecialSymbolSyntax.Kind.SMALL_PI -> tag("mo") { append("π") } } is OperandSyntax -> if (node.parentheses) { diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index afdf12b04..14e14404c 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -85,9 +85,10 @@ public open class FeaturedMathRendererWithPostProcess( BinaryOperator.Default, UnaryOperator.Default, - // Pretty printing for numerics + // Pretty printing for some objects PrettyPrintFloats.Default, PrettyPrintIntegers.Default, + PrettyPrintPi.Default, // Printing terminal nodes as string PrintNumeric, @@ -96,7 +97,7 @@ public open class FeaturedMathRendererWithPostProcess( listOf( SimplifyParentheses.Default, BetterMultiplication, - ) + ), ) } } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt index 4c85adcfc..febb6e5af 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -101,6 +101,11 @@ public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() * The infinity (∞) symbol. */ INFINITY, + + /** + * The Pi (π) symbol. + */ + SMALL_PI; } } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index 6e66d3ca3..95108ba45 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -118,6 +118,25 @@ public class PrettyPrintIntegers(public val types: Set>) : Re } } +/** + * Special printing for symbols meaning Pi. + * + * @property symbols The allowed symbols. + */ +public class PrettyPrintPi(public val symbols: Set) : RenderFeature { + public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { + if (node !is MST.Symbolic || node.value !in symbols) return null + return SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI) + } + + public companion object { + /** + * The default instance containing `pi`. + */ + public val Default: PrettyPrintPi = PrettyPrintPi(setOf("pi")) + } +} + /** * Abstract printing of unary operations which discards [MST] if their operation is not in [operations] or its type is * not [MST.Unary]. diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt index b10f7ed4e..5850ea23d 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt @@ -45,6 +45,11 @@ internal class TestFeatures { testLatex(Numeric(-42), "-42") } + @Test + fun prettyPrintPi() { + testLatex("pi", "\\pi") + } + @Test fun binaryPlus() = testLatex("2+2", "2+2") diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt index 9c1009042..599bee436 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt @@ -16,7 +16,10 @@ internal class TestLatex { fun operatorName() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") @Test - fun specialSymbol() = testLatex(MST.Numeric(Double.POSITIVE_INFINITY), "\\infty") + fun specialSymbol() { + testLatex(MST.Numeric(Double.POSITIVE_INFINITY), "\\infty") + testLatex("pi", "\\pi") + } @Test fun operand() { diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt index c9a462840..6fadef6cd 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt @@ -19,7 +19,10 @@ internal class TestMathML { ) @Test - fun specialSymbol() = testMathML(MST.Numeric(Double.POSITIVE_INFINITY), "") + fun specialSymbol() { + testMathML(MST.Numeric(Double.POSITIVE_INFINITY), "") + testMathML("pi", "π") + } @Test fun operand() { diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 76f6c6ff5..4f229cabd 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -24,7 +24,7 @@ public class DerivativeStructureField( public override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) } public override val one: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order, 1.0) } - override fun number(value: Number): DerivativeStructure = const(value.toDouble()) + public override fun number(value: Number): DerivativeStructure = const(value.toDouble()) /** * A class that implements both [DerivativeStructure] and a [Symbol] @@ -35,10 +35,10 @@ public class DerivativeStructureField( symbol: Symbol, value: Double, ) : DerivativeStructure(size, order, index, value), Symbol { - override val identity: String = symbol.identity - override fun toString(): String = identity - override fun equals(other: Any?): Boolean = this.identity == (other as? Symbol)?.identity - override fun hashCode(): Int = identity.hashCode() + public override val identity: String = symbol.identity + public override fun toString(): String = identity + public override fun equals(other: Any?): Boolean = this.identity == (other as? Symbol)?.identity + public override fun hashCode(): Int = identity.hashCode() } /** @@ -48,10 +48,10 @@ public class DerivativeStructureField( key.identity to DerivativeStructureSymbol(numberOfVariables, index, key, value) }.toMap() - override fun const(value: Double): DerivativeStructure = DerivativeStructure(numberOfVariables, order, value) + public override fun const(value: Double): DerivativeStructure = DerivativeStructure(numberOfVariables, order, value) - override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol? = variables[value] - override fun bindSymbol(value: String): DerivativeStructureSymbol = variables.getValue(value) + public override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol? = variables[value] + public override fun bindSymbol(value: String): DerivativeStructureSymbol = variables.getValue(value) public fun bindSymbolOrNull(symbol: Symbol): DerivativeStructureSymbol? = variables[symbol.identity] public fun bindSymbol(symbol: Symbol): DerivativeStructureSymbol = variables.getValue(symbol.identity) @@ -64,7 +64,7 @@ public class DerivativeStructureField( public fun DerivativeStructure.derivative(vararg symbols: Symbol): Double = derivative(symbols.toList()) - override fun DerivativeStructure.unaryMinus(): DerivativeStructure = negate() + public override fun DerivativeStructure.unaryMinus(): DerivativeStructure = negate() public override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b) diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt index e98b41b9b..aa97c6463 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt @@ -121,8 +121,8 @@ public object ComplexField : ExtendedField, Norm, Num /** * Adds complex number to real one. * - * @receiver the addend. - * @param c the augend. + * @receiver the augend. + * @param c the addend. * @return the sum. */ public operator fun Double.plus(c: Complex): Complex = add(this.toComplex(), c) @@ -139,8 +139,8 @@ public object ComplexField : ExtendedField, Norm, Num /** * Adds real number to complex one. * - * @receiver the addend. - * @param d the augend. + * @receiver the augend. + * @param d the addend. * @return the sum. */ public operator fun Complex.plus(d: Double): Complex = d + this diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt index d11f2b7db..701b77df1 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt @@ -22,10 +22,10 @@ public class ComplexFieldND( NumbersAddOperations>, ExtendedField> { - override val zero: BufferND by lazy { produce { zero } } - override val one: BufferND by lazy { produce { one } } + public override val zero: BufferND by lazy { produce { zero } } + public override val one: BufferND by lazy { produce { one } } - override fun number(value: Number): BufferND { + public override fun number(value: Number): BufferND { val d = value.toComplex() // minimize conversions return produce { d } } @@ -76,25 +76,25 @@ public class ComplexFieldND( // return BufferedNDFieldElement(this, buffer) // } - override fun power(arg: StructureND, pow: Number): BufferND = arg.map { power(it, pow) } + public override fun power(arg: StructureND, pow: Number): BufferND = arg.map { power(it, pow) } - override fun exp(arg: StructureND): BufferND = arg.map { exp(it) } + public override fun exp(arg: StructureND): BufferND = arg.map { exp(it) } - override fun ln(arg: StructureND): BufferND = arg.map { ln(it) } + public override fun ln(arg: StructureND): BufferND = arg.map { ln(it) } - override fun sin(arg: StructureND): BufferND = arg.map { sin(it) } - override fun cos(arg: StructureND): BufferND = arg.map { cos(it) } - override fun tan(arg: StructureND): BufferND = arg.map { tan(it) } - override fun asin(arg: StructureND): BufferND = arg.map { asin(it) } - override fun acos(arg: StructureND): BufferND = arg.map { acos(it) } - override fun atan(arg: StructureND): BufferND = arg.map { atan(it) } + public override fun sin(arg: StructureND): BufferND = arg.map { sin(it) } + public override fun cos(arg: StructureND): BufferND = arg.map { cos(it) } + public override fun tan(arg: StructureND): BufferND = arg.map { tan(it) } + public override fun asin(arg: StructureND): BufferND = arg.map { asin(it) } + public override fun acos(arg: StructureND): BufferND = arg.map { acos(it) } + public override fun atan(arg: StructureND): BufferND = arg.map { atan(it) } - override fun sinh(arg: StructureND): BufferND = arg.map { sinh(it) } - override fun cosh(arg: StructureND): BufferND = arg.map { cosh(it) } - override fun tanh(arg: StructureND): BufferND = arg.map { tanh(it) } - override fun asinh(arg: StructureND): BufferND = arg.map { asinh(it) } - override fun acosh(arg: StructureND): BufferND = arg.map { acosh(it) } - override fun atanh(arg: StructureND): BufferND = arg.map { atanh(it) } + public override fun sinh(arg: StructureND): BufferND = arg.map { sinh(it) } + public override fun cosh(arg: StructureND): BufferND = arg.map { cosh(it) } + public override fun tanh(arg: StructureND): BufferND = arg.map { tanh(it) } + public override fun asinh(arg: StructureND): BufferND = arg.map { asinh(it) } + public override fun acosh(arg: StructureND): BufferND = arg.map { acosh(it) } + public override fun atanh(arg: StructureND): BufferND = arg.map { atanh(it) } } diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index f4724a50e..f76372a3d 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -121,6 +121,8 @@ public class space/kscience/kmath/expressions/FunctionalExpressionExtendedField public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; public fun atanh (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cos (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; @@ -152,6 +154,8 @@ public class space/kscience/kmath/expressions/FunctionalExpressionExtendedField public class space/kscience/kmath/expressions/FunctionalExpressionField : space/kscience/kmath/expressions/FunctionalExpressionRing, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/ScaleOperations { public fun (Lspace/kscience/kmath/operations/Field;)V public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public final fun div (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; @@ -235,6 +239,8 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffExtendedField public fun atan (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; public fun atanh (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cos (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; @@ -708,6 +714,8 @@ public final class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/St public class space/kscience/kmath/nd/BufferedFieldND : space/kscience/kmath/nd/BufferedRingND, space/kscience/kmath/nd/FieldND { public fun ([ILspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;)V public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; @@ -821,6 +829,8 @@ public final class space/kscience/kmath/nd/DoubleFieldND : space/kscience/kmath/ public fun atan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; public fun atanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; @@ -997,6 +1007,8 @@ public final class space/kscience/kmath/nd/ShapeMismatchException : java/lang/Ru public final class space/kscience/kmath/nd/ShortRingND : space/kscience/kmath/nd/BufferedRingND, space/kscience/kmath/operations/NumbersAddOperations { public fun ([I)V + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/nd/BufferND; public synthetic fun getZero ()Ljava/lang/Object; @@ -1447,6 +1459,7 @@ public abstract interface class space/kscience/kmath/operations/ExtendedField : public abstract fun acosh (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun asinh (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun atanh (Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public abstract fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public abstract fun sinh (Ljava/lang/Object;)Ljava/lang/Object; @@ -1914,6 +1927,7 @@ public final class space/kscience/kmath/operations/NumbersAddOperations$DefaultI } public abstract interface class space/kscience/kmath/operations/NumericAlgebra : space/kscience/kmath/operations/Algebra { + public abstract fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public abstract fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public abstract fun number (Ljava/lang/Number;)Ljava/lang/Object; @@ -1934,6 +1948,11 @@ public final class space/kscience/kmath/operations/NumericAlgebra$DefaultImpls { public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } +public final class space/kscience/kmath/operations/NumericAlgebraKt { + public static final fun getE (Lspace/kscience/kmath/operations/NumericAlgebra;)Ljava/lang/Object; + public static final fun getPi (Lspace/kscience/kmath/operations/NumericAlgebra;)Ljava/lang/Object; +} + public final class space/kscience/kmath/operations/OptionalOperationsKt { } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index 775a49aad..9fb8f28c8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -19,8 +19,10 @@ public abstract class FunctionalExpressionAlgebra>( /** * Builds an Expression to access a variable. */ - override fun bindSymbolOrNull(value: String): Expression? = Expression { arguments -> - arguments[StringSymbol(value)] ?: error("Argument not found: $value") + public override fun bindSymbolOrNull(value: String): Expression? = Expression { arguments -> + algebra.bindSymbolOrNull(value) + ?: arguments[StringSymbol(value)] + ?: error("Symbol '$value' is not supported in $this") } /** @@ -49,7 +51,7 @@ public open class FunctionalExpressionGroup>( ) : FunctionalExpressionAlgebra(algebra), Group> { public override val zero: Expression get() = const(algebra.zero) - override fun Expression.unaryMinus(): Expression = + public override fun Expression.unaryMinus(): Expression = unaryOperation(GroupOperations.MINUS_OPERATION, this) /** @@ -117,16 +119,21 @@ public open class FunctionalExpressionField>( public override fun binaryOperationFunction(operation: String): (left: Expression, right: Expression) -> Expression = super.binaryOperationFunction(operation) - override fun scale(a: Expression, value: Double): Expression = algebra { + public override fun scale(a: Expression, value: Double): Expression = algebra { Expression { args -> a(args) * value } } + + public override fun bindSymbolOrNull(value: String): Expression? = + super.bindSymbolOrNull(value) } public open class FunctionalExpressionExtendedField>( algebra: A, ) : FunctionalExpressionField(algebra), ExtendedField> { + public override fun number(value: Number): Expression = const(algebra.number(value)) - override fun number(value: Number): Expression = const(algebra.number(value)) + public override fun sqrt(arg: Expression): Expression = + unaryOperationFunction(PowerOperations.SQRT_OPERATION)(arg) public override fun sin(arg: Expression): Expression = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg) @@ -157,6 +164,8 @@ public open class FunctionalExpressionExtendedField>( public override fun binaryOperationFunction(operation: String): (left: Expression, right: Expression) -> Expression = super.binaryOperationFunction(operation) + + public override fun bindSymbol(value: String): Expression = super.bindSymbol(value) } public inline fun > A.expressionInSpace(block: FunctionalExpressionGroup.() -> Expression): Expression = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt index d3b65107d..a832daa14 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -337,9 +337,11 @@ public class SimpleAutoDiffExtendedField>( ) : ExtendedField>, ScaleOperations>, SimpleAutoDiffField(context, bindings) { - override fun number(value: Number): AutoDiffValue = const { number(value) } + override fun bindSymbol(value: String): AutoDiffValue = super.bindSymbol(value) - override fun scale(a: AutoDiffValue, value: Double): AutoDiffValue = a * number(value) + public override fun number(value: Number): AutoDiffValue = const { number(value) } + + public override fun scale(a: AutoDiffValue, value: Double): AutoDiffValue = a * number(value) // x ^ 2 public fun sqr(x: AutoDiffValue): AutoDiffValue = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt index 2821a6648..b5aa56bd3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt @@ -120,8 +120,8 @@ public interface GroupND> : Group>, AlgebraND, b: StructureND): StructureND = @@ -141,8 +141,8 @@ public interface GroupND> : Group>, AlgebraND.plus(arg: T): StructureND = this.map { value -> add(arg, value) } @@ -159,8 +159,8 @@ public interface GroupND> : Group>, AlgebraND): StructureND = arg.map { value -> add(this@plus, value) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt index d38ed02da..40d16cd91 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt @@ -17,15 +17,15 @@ public class DoubleFieldND( ScaleOperations>, ExtendedField> { - override val zero: BufferND by lazy { produce { zero } } - override val one: BufferND by lazy { produce { one } } + public override val zero: BufferND by lazy { produce { zero } } + public override val one: BufferND by lazy { produce { one } } - override fun number(value: Number): BufferND { + public override fun number(value: Number): BufferND { val d = value.toDouble() // minimize conversions return produce { d } } - override val StructureND.buffer: DoubleBuffer + public override val StructureND.buffer: DoubleBuffer get() = when { !shape.contentEquals(this@DoubleFieldND.shape) -> throw ShapeMismatchException( this@DoubleFieldND.shape, @@ -36,7 +36,7 @@ public class DoubleFieldND( } @Suppress("OVERRIDE_BY_INLINE") - override inline fun StructureND.map( + public override inline fun StructureND.map( transform: DoubleField.(Double) -> Double, ): BufferND { val buffer = DoubleBuffer(strides.linearSize) { offset -> DoubleField.transform(buffer.array[offset]) } @@ -44,7 +44,7 @@ public class DoubleFieldND( } @Suppress("OVERRIDE_BY_INLINE") - override inline fun produce(initializer: DoubleField.(IntArray) -> Double): BufferND { + public override inline fun produce(initializer: DoubleField.(IntArray) -> Double): BufferND { val array = DoubleArray(strides.linearSize) { offset -> val index = strides.index(offset) DoubleField.initializer(index) @@ -53,7 +53,7 @@ public class DoubleFieldND( } @Suppress("OVERRIDE_BY_INLINE") - override inline fun StructureND.mapIndexed( + public override inline fun StructureND.mapIndexed( transform: DoubleField.(index: IntArray, Double) -> Double, ): BufferND = BufferND( strides, @@ -65,7 +65,7 @@ public class DoubleFieldND( }) @Suppress("OVERRIDE_BY_INLINE") - override inline fun combine( + public override inline fun combine( a: StructureND, b: StructureND, transform: DoubleField.(Double, Double) -> Double, @@ -76,27 +76,26 @@ public class DoubleFieldND( return BufferND(strides, buffer) } - override fun scale(a: StructureND, value: Double): StructureND = a.map { it * value } + public override fun scale(a: StructureND, value: Double): StructureND = a.map { it * value } - override fun power(arg: StructureND, pow: Number): BufferND = arg.map { power(it, pow) } + public override fun power(arg: StructureND, pow: Number): BufferND = arg.map { power(it, pow) } - override fun exp(arg: StructureND): BufferND = arg.map { exp(it) } + public override fun exp(arg: StructureND): BufferND = arg.map { exp(it) } + public override fun ln(arg: StructureND): BufferND = arg.map { ln(it) } - override fun ln(arg: StructureND): BufferND = arg.map { ln(it) } + public override fun sin(arg: StructureND): BufferND = arg.map { sin(it) } + public override fun cos(arg: StructureND): BufferND = arg.map { cos(it) } + public override fun tan(arg: StructureND): BufferND = arg.map { tan(it) } + public override fun asin(arg: StructureND): BufferND = arg.map { asin(it) } + public override fun acos(arg: StructureND): BufferND = arg.map { acos(it) } + public override fun atan(arg: StructureND): BufferND = arg.map { atan(it) } - override fun sin(arg: StructureND): BufferND = arg.map { sin(it) } - override fun cos(arg: StructureND): BufferND = arg.map { cos(it) } - override fun tan(arg: StructureND): BufferND = arg.map { tan(it) } - override fun asin(arg: StructureND): BufferND = arg.map { asin(it) } - override fun acos(arg: StructureND): BufferND = arg.map { acos(it) } - override fun atan(arg: StructureND): BufferND = arg.map { atan(it) } - - override fun sinh(arg: StructureND): BufferND = arg.map { sinh(it) } - override fun cosh(arg: StructureND): BufferND = arg.map { cosh(it) } - override fun tanh(arg: StructureND): BufferND = arg.map { tanh(it) } - override fun asinh(arg: StructureND): BufferND = arg.map { asinh(it) } - override fun acosh(arg: StructureND): BufferND = arg.map { acosh(it) } - override fun atanh(arg: StructureND): BufferND = arg.map { atanh(it) } + public override fun sinh(arg: StructureND): BufferND = arg.map { sinh(it) } + public override fun cosh(arg: StructureND): BufferND = arg.map { cosh(it) } + public override fun tanh(arg: StructureND): BufferND = arg.map { tanh(it) } + public override fun asinh(arg: StructureND): BufferND = arg.map { asinh(it) } + public override fun acosh(arg: StructureND): BufferND = arg.map { acosh(it) } + public override fun atanh(arg: StructureND): BufferND = arg.map { atanh(it) } } public fun AlgebraND.Companion.real(vararg shape: Int): DoubleFieldND = DoubleFieldND(shape) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 78ada6f5c..1b84b2c63 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -119,8 +119,8 @@ public interface GroupOperations : Algebra { /** * Addition of two elements. * - * @param a the addend. - * @param b the augend. + * @param a the augend. + * @param b the addend. * @return the sum. */ public fun add(a: T, b: T): T @@ -146,8 +146,8 @@ public interface GroupOperations : Algebra { /** * Addition of two elements. * - * @receiver the addend. - * @param b the augend. + * @receiver the augend. + * @param b the addend. * @return the sum. */ public operator fun T.plus(b: T): T = add(this, b) @@ -293,5 +293,5 @@ public interface FieldOperations : RingOperations { * @param T the type of element of this field. */ public interface Field : Ring, FieldOperations, ScaleOperations, NumericAlgebra { - override fun number(value: Number): T = scale(one, value.toDouble()) -} \ No newline at end of file + public override fun number(value: Number): T = scale(one, value.toDouble()) +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt index b2b5911df..c0380a197 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt @@ -46,7 +46,8 @@ public operator fun , S : NumbersAddOperations> T.mi /** * Adds element to this one. * - * @param b the augend. + * @receiver the augend. + * @param b the addend. * @return the sum. */ public operator fun , S : Group> T.plus(b: T): T = @@ -58,11 +59,11 @@ public operator fun , S : Group> T.plus(b: T): T = //public operator fun , S : Space> Number.times(element: T): T = // element.times(this) - /** * Multiplies this element by another one. * - * @param b the multiplicand. + * @receiver the multiplicand. + * @param b the multiplier. * @return the product. */ public operator fun , R : Ring> T.times(b: T): T = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt index bd5f5951f..84d4f8064 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt @@ -1,6 +1,8 @@ package space.kscience.kmath.operations import space.kscience.kmath.misc.UnstableKMathAPI +import kotlin.math.E +import kotlin.math.PI /** * An algebraic structure where elements can have numeric representation. @@ -79,8 +81,26 @@ public interface NumericAlgebra : Algebra { */ public fun rightSideNumberOperation(operation: String, left: T, right: Number): T = rightSideNumberOperationFunction(operation)(left, right) + + public override fun bindSymbolOrNull(value: String): T? = when (value) { + "pi" -> number(PI) + "e" -> number(E) + else -> super.bindSymbolOrNull(value) + } } +/** + * The π mathematical constant. + */ +public val NumericAlgebra.pi: T + get() = bindSymbolOrNull("pi") ?: number(PI) + +/** + * The *e* mathematical constant. + */ +public val NumericAlgebra.e: T + get() = number(E) + /** * Scale by scalar operations */ @@ -131,16 +151,16 @@ public interface NumbersAddOperations : Group, NumericAlgebra { /** * Addition of element and scalar. * - * @receiver the addend. - * @param b the augend. + * @receiver the augend. + * @param b the addend. */ public operator fun T.plus(b: Number): T = this + number(b) /** * Addition of scalar and element. * - * @receiver the addend. - * @param b the augend. + * @receiver the augend. + * @param b the addend. */ public operator fun Number.plus(b: T): T = b + this diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt index 0101b058a..37257f0cf 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt @@ -44,6 +44,12 @@ public interface ExtendedField : ExtendedFieldOperations, Field, Numeri public override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one))) public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2.0 + public override fun bindSymbol(value: String): T = when (value) { + "pi" -> pi + "e" -> e + else -> super.bindSymbol(value) + } + public override fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T = when (operation) { PowerOperations.POW_OPERATION -> ::power @@ -56,10 +62,10 @@ public interface ExtendedField : ExtendedFieldOperations, Field, Numeri */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object DoubleField : ExtendedField, Norm, ScaleOperations { - public override val zero: Double = 0.0 - public override val one: Double = 1.0 + public override inline val zero: Double get() = 0.0 + public override inline val one: Double get() = 1.0 - override fun number(value: Number): Double = value.toDouble() + public override fun number(value: Number): Double = value.toDouble() public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double = when (operation) { @@ -68,13 +74,11 @@ public object DoubleField : ExtendedField, Norm, ScaleOp } public override inline fun add(a: Double, b: Double): Double = a + b -// public override inline fun multiply(a: Double, k: Number): Double = a * k.toDouble() -// override fun divide(a: Double, k: Number): Double = a / k.toDouble() public override inline fun multiply(a: Double, b: Double): Double = a * b public override inline fun divide(a: Double, b: Double): Double = a / b - override fun scale(a: Double, value: Double): Double = a * value + public override fun scale(a: Double, value: Double): Double = a * value public override inline fun sin(arg: Double): Double = kotlin.math.sin(arg) public override inline fun cos(arg: Double): Double = kotlin.math.cos(arg) @@ -108,10 +112,10 @@ public object DoubleField : ExtendedField, Norm, ScaleOp */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object FloatField : ExtendedField, Norm { - public override val zero: Float = 0.0f - public override val one: Float = 1.0f + public override inline val zero: Float get() = 0.0f + public override inline val one: Float get() = 1.0f - override fun number(value: Number): Float = value.toFloat() + public override fun number(value: Number): Float = value.toFloat() public override fun binaryOperationFunction(operation: String): (left: Float, right: Float) -> Float = when (operation) { @@ -120,7 +124,7 @@ public object FloatField : ExtendedField, Norm { } public override inline fun add(a: Float, b: Float): Float = a + b - override fun scale(a: Float, value: Double): Float = a * value.toFloat() + public override fun scale(a: Float, value: Double): Float = a * value.toFloat() public override inline fun multiply(a: Float, b: Float): Float = a * b @@ -158,13 +162,13 @@ public object FloatField : ExtendedField, Norm { */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object IntRing : Ring, Norm, NumericAlgebra { - public override val zero: Int + public override inline val zero: Int get() = 0 - public override val one: Int + public override inline val one: Int get() = 1 - override fun number(value: Number): Int = value.toInt() + public override fun number(value: Number): Int = value.toInt() public override inline fun add(a: Int, b: Int): Int = a + b public override inline fun multiply(a: Int, b: Int): Int = a * b public override inline fun norm(arg: Int): Int = abs(arg) @@ -180,13 +184,13 @@ public object IntRing : Ring, Norm, NumericAlgebra { */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object ShortRing : Ring, Norm, NumericAlgebra { - public override val zero: Short + public override inline val zero: Short get() = 0 - public override val one: Short + public override inline val one: Short get() = 1 - override fun number(value: Number): Short = value.toShort() + public override fun number(value: Number): Short = value.toShort() public override inline fun add(a: Short, b: Short): Short = (a + b).toShort() public override inline fun multiply(a: Short, b: Short): Short = (a * b).toShort() public override fun norm(arg: Short): Short = if (arg > 0) arg else (-arg).toShort() @@ -202,13 +206,13 @@ public object ShortRing : Ring, Norm, NumericAlgebra */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object ByteRing : Ring, Norm, NumericAlgebra { - public override val zero: Byte + public override inline val zero: Byte get() = 0 - public override val one: Byte + public override inline val one: Byte get() = 1 - override fun number(value: Number): Byte = value.toByte() + public override fun number(value: Number): Byte = value.toByte() public override inline fun add(a: Byte, b: Byte): Byte = (a + b).toByte() public override inline fun multiply(a: Byte, b: Byte): Byte = (a * b).toByte() public override fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte() @@ -224,13 +228,13 @@ public object ByteRing : Ring, Norm, NumericAlgebra { */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object LongRing : Ring, Norm, NumericAlgebra { - public override val zero: Long + public override inline val zero: Long get() = 0L - public override val one: Long + public override inline val one: Long get() = 1L - override fun number(value: Number): Long = value.toLong() + public override fun number(value: Number): Long = value.toLong() public override inline fun add(a: Long, b: Long): Long = a + b public override inline fun multiply(a: Long, b: Long): Long = a * b public override fun norm(arg: Long): Long = abs(arg) diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt index 3c9d6a2e4..908c5775b 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt @@ -3,7 +3,6 @@ package space.kscience.kmath.stat import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking - import space.kscience.kmath.streaming.chunked import kotlin.test.Test diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api index e209c863c..0e4eac77e 100644 --- a/kmath-viktor/api/kmath-viktor.api +++ b/kmath-viktor/api/kmath-viktor.api @@ -126,7 +126,7 @@ public final class space/kscience/kmath/viktor/ViktorFieldND : space/kscience/km public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; public fun sqrt (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; - public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun tan-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; public fun tanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun times (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt index 420bcac90..49cd3ebd9 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt @@ -41,7 +41,6 @@ public class ViktorFieldND(public override val shape: IntArray) : FieldND.unaryMinus(): StructureND = -1 * this + public override fun StructureND.unaryMinus(): StructureND = -1 * this public override fun StructureND.map(transform: DoubleField.(Double) -> Double): ViktorStructureND = F64Array(*this@ViktorFieldND.shape).apply { @@ -100,24 +99,21 @@ public class ViktorFieldND(public override val shape: IntArray) : FieldND.plus(arg: Double): ViktorStructureND = (f64Buffer.plus(arg)).asStructure() - override fun number(value: Number): ViktorStructureND = + public override fun number(value: Number): ViktorStructureND = F64Array.full(init = value.toDouble(), shape = shape).asStructure() - override fun sin(arg: StructureND): ViktorStructureND = arg.map { sin(it) } + public override fun sin(arg: StructureND): ViktorStructureND = arg.map { sin(it) } + public override fun cos(arg: StructureND): ViktorStructureND = arg.map { cos(it) } + public override fun tan(arg: StructureND): ViktorStructureND = arg.map { tan(it) } + public override fun asin(arg: StructureND): ViktorStructureND = arg.map { asin(it) } + public override fun acos(arg: StructureND): ViktorStructureND = arg.map { acos(it) } + public override fun atan(arg: StructureND): ViktorStructureND = arg.map { atan(it) } - override fun cos(arg: StructureND): ViktorStructureND = arg.map { cos(it) } + public override fun power(arg: StructureND, pow: Number): ViktorStructureND = arg.map { it.pow(pow) } - override fun asin(arg: StructureND): ViktorStructureND = arg.map { asin(it) } + public override fun exp(arg: StructureND): ViktorStructureND = arg.f64Buffer.exp().asStructure() - override fun acos(arg: StructureND): ViktorStructureND = arg.map { acos(it) } - - override fun atan(arg: StructureND): ViktorStructureND = arg.map { atan(it) } - - override fun power(arg: StructureND, pow: Number): ViktorStructureND = arg.map { it.pow(pow) } - - override fun exp(arg: StructureND): ViktorStructureND = arg.f64Buffer.exp().asStructure() - - override fun ln(arg: StructureND): ViktorStructureND = arg.f64Buffer.log().asStructure() + public override fun ln(arg: StructureND): ViktorStructureND = arg.f64Buffer.log().asStructure() } -public fun ViktorNDField(vararg shape: Int): ViktorFieldND = ViktorFieldND(shape) \ No newline at end of file +public fun ViktorNDField(vararg shape: Int): ViktorFieldND = ViktorFieldND(shape) From 814eab8cde1dff4b94b49efbb8d93c6b0bc06002 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Tue, 6 Apr 2021 00:06:14 +0300 Subject: [PATCH 169/393] implement svd function and tests for it --- .../core/DoubleLinearOpsTensorAlgebra.kt | 77 ++++++++++++++++++- .../core/TestDoubleLinearOpsAlgebra.kt | 32 ++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index c571fe446..fbd9da18e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -3,6 +3,8 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import kotlin.math.abs +import kotlin.math.min public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -89,8 +91,81 @@ public class DoubleLinearOpsTensorAlgebra : return qTensor to rTensor } + internal fun svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { + val (n, m) = a.shape + var v: DoubleTensor + val b: DoubleTensor + if (n > m) { + b = a.transpose(0, 1).dot(a) + v = DoubleTensor(intArrayOf(m), getRandomNormals(m, 0)) + } else { + b = a.dot(a.transpose(0, 1)) + v = DoubleTensor(intArrayOf(n), getRandomNormals(n, 0)) + } + + var lastV: DoubleTensor + while (true) { + lastV = v + v = b.dot(lastV) + val norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + v = v.times(1.0 / norm) + if (abs(v.dot(lastV).value()) > 1 - epsilon) { + return v + } + } + } + override fun DoubleTensor.svd(): Triple { - TODO("ALYA") + val size = this.shape.size + val commonShape = this.shape.sliceArray(0 until size - 2) + val (n, m) = this.shape.sliceArray(size - 2 until size) + val resU = zeros(commonShape + intArrayOf(n, min(n, m))) + val resS = zeros(commonShape + intArrayOf(min(n, m))) + val resV = zeros(commonShape + intArrayOf(min(n, m), m)) + + for ((matrix, USV) in this.matrixSequence() + .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) { + val res = ArrayList>(0) + val (matrixU, SV) = USV + val (matrixS, matrixV) = SV + + for (k in 0 until min(n, m)) { + var a = matrix.asTensor().copy() + for ((singularValue, u, v) in res.slice(0 until k)) { + val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) + for (i in 0 until u.shape[0]) { + for (j in 0 until v.shape[0]) { + outerProduct[i * v.shape[0] + j] = u[i].value() * v[j].value() + } + } + a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct)) + } + var v: DoubleTensor + var u: DoubleTensor + var norm: Double + if (n > m) { + v = svd1d(a) + u = matrix.asTensor().dot(v) + norm = DoubleAnalyticTensorAlgebra { (u dot u).sqrt().value() } + u = u.times(1.0 / norm) + } else { + u = svd1d(a) + v = matrix.asTensor().transpose(0, 1).dot(u) + norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + v = v.times(1.0 / norm) + } + + res.add(Triple(norm, u, v)) + } + + val s = res.map { it.first }.toDoubleArray() + val uBuffer = res.map { it.second }.flatMap { it.buffer.array().toList() }.toDoubleArray() + val vBuffer = res.map { it.third }.flatMap { it.buffer.array().toList() }.toDoubleArray() + uBuffer.copyInto(matrixU.buffer.array()) + s.copyInto(matrixS.buffer.array()) + vBuffer.copyInto(matrixV.buffer.array()) + } + return Triple(resU, resS, resV.transpose(size - 2, size - 1)) } override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index b79c54dd1..843707153 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -122,4 +122,36 @@ class TestDoubleLinearOpsTensorAlgebra { assertTrue { p.dot(tensor).buffer.array().epsEqual(l.dot(u).buffer.array()) } } + + @Test + fun svd1d() = DoubleLinearOpsTensorAlgebra { + val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + + val res = svd1d(tensor2) + + assertTrue(res.shape contentEquals intArrayOf(2)) + assertTrue { abs(abs(res.buffer.array()[res.bufferStart]) - 0.386) < 0.01} + assertTrue { abs(abs(res.buffer.array()[res.bufferStart + 1]) - 0.922) < 0.01} + } + + @Test + fun svd() = DoubleLinearOpsTensorAlgebra { + val epsilon = 1e-10 + fun test_tensor(tensor: DoubleTensor) { + val svd = tensor.svd() + + val tensorSVD = svd.first + .dot( + diagonalEmbedding(svd.second, 0, 0, 1) + .dot(svd.third.transpose(0, 1)) + ) + + for ((x1, x2) in tensor.buffer.array() zip tensorSVD.buffer.array()) { + assertTrue { abs(x1 - x2) < epsilon } + } + } + test_tensor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) + test_tensor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) + + } } From 4336788a6ba846af6a63be1352d1bec1c1f39b56 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 6 Apr 2021 09:00:13 +0100 Subject: [PATCH 170/393] Moving Alya's SVD implementation to linutils --- .../core/DoubleLinearOpsTensorAlgebra.kt | 66 +--------------- .../kscience/kmath/tensors/core/linutils.kt | 76 ++++++++++++++++++- .../core/TestDoubleLinearOpsAlgebra.kt | 4 +- 3 files changed, 78 insertions(+), 68 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index fbd9da18e..7db812d9d 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -91,29 +91,6 @@ public class DoubleLinearOpsTensorAlgebra : return qTensor to rTensor } - internal fun svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { - val (n, m) = a.shape - var v: DoubleTensor - val b: DoubleTensor - if (n > m) { - b = a.transpose(0, 1).dot(a) - v = DoubleTensor(intArrayOf(m), getRandomNormals(m, 0)) - } else { - b = a.dot(a.transpose(0, 1)) - v = DoubleTensor(intArrayOf(n), getRandomNormals(n, 0)) - } - - var lastV: DoubleTensor - while (true) { - lastV = v - v = b.dot(lastV) - val norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } - v = v.times(1.0 / norm) - if (abs(v.dot(lastV).value()) > 1 - epsilon) { - return v - } - } - } override fun DoubleTensor.svd(): Triple { val size = this.shape.size @@ -124,47 +101,8 @@ public class DoubleLinearOpsTensorAlgebra : val resV = zeros(commonShape + intArrayOf(min(n, m), m)) for ((matrix, USV) in this.matrixSequence() - .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) { - val res = ArrayList>(0) - val (matrixU, SV) = USV - val (matrixS, matrixV) = SV - - for (k in 0 until min(n, m)) { - var a = matrix.asTensor().copy() - for ((singularValue, u, v) in res.slice(0 until k)) { - val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) - for (i in 0 until u.shape[0]) { - for (j in 0 until v.shape[0]) { - outerProduct[i * v.shape[0] + j] = u[i].value() * v[j].value() - } - } - a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct)) - } - var v: DoubleTensor - var u: DoubleTensor - var norm: Double - if (n > m) { - v = svd1d(a) - u = matrix.asTensor().dot(v) - norm = DoubleAnalyticTensorAlgebra { (u dot u).sqrt().value() } - u = u.times(1.0 / norm) - } else { - u = svd1d(a) - v = matrix.asTensor().transpose(0, 1).dot(u) - norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } - v = v.times(1.0 / norm) - } - - res.add(Triple(norm, u, v)) - } - - val s = res.map { it.first }.toDoubleArray() - val uBuffer = res.map { it.second }.flatMap { it.buffer.array().toList() }.toDoubleArray() - val vBuffer = res.map { it.third }.flatMap { it.buffer.array().toList() }.toDoubleArray() - uBuffer.copyInto(matrixU.buffer.array()) - s.copyInto(matrixS.buffer.array()) - vBuffer.copyInto(matrixV.buffer.array()) - } + .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) + svdHelper(matrix.asTensor(), USV, m, n) return Triple(resU, resS, resV.transpose(size - 2, size - 1)) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index f6cf71b07..e1d5c1819 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -4,6 +4,8 @@ import space.kscience.kmath.nd.MutableStructure1D import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import kotlin.math.abs +import kotlin.math.min import kotlin.math.sqrt @@ -195,8 +197,8 @@ internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper( checkSquareMatrix(matrix.shape) val n = matrix.shape[0] val qM = q.as2D() - val matrixT = matrix.transpose(0,1) - val qT = q.transpose(0,1) + val matrixT = matrix.transpose(0, 1) + val qT = q.transpose(0, 1) for (j in 0 until n) { val v = matrixT[j] @@ -216,3 +218,73 @@ internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper( } } } + +internal inline fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { + val (n, m) = a.shape + var v: DoubleTensor + val b: DoubleTensor + if (n > m) { + b = a.transpose(0, 1).dot(a) + v = DoubleTensor(intArrayOf(m), getRandomNormals(m, 0)) + } else { + b = a.dot(a.transpose(0, 1)) + v = DoubleTensor(intArrayOf(n), getRandomNormals(n, 0)) + } + + var lastV: DoubleTensor + while (true) { + lastV = v + v = b.dot(lastV) + val norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + v = v.times(1.0 / norm) + if (abs(v.dot(lastV).value()) > 1 - epsilon) { + return v + } + } +} + +internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( + matrix: DoubleTensor, + USV: Pair, Pair, BufferedTensor>>, + m: Int, n: Int +): Unit { + val res = ArrayList>(0) + val (matrixU, SV) = USV + val (matrixS, matrixV) = SV + + for (k in 0 until min(n, m)) { + var a = matrix.copy() + for ((singularValue, u, v) in res.slice(0 until k)) { + val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) + for (i in 0 until u.shape[0]) { + for (j in 0 until v.shape[0]) { + outerProduct[i * v.shape[0] + j] = u[i].value() * v[j].value() + } + } + a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct)) + } + var v: DoubleTensor + var u: DoubleTensor + var norm: Double + if (n > m) { + v = svd1d(a) + u = matrix.dot(v) + norm = DoubleAnalyticTensorAlgebra { (u dot u).sqrt().value() } + u = u.times(1.0 / norm) + } else { + u = svd1d(a) + v = matrix.transpose(0, 1).dot(u) + norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + v = v.times(1.0 / norm) + } + + res.add(Triple(norm, u, v)) + } + + val s = res.map { it.first }.toDoubleArray() + val uBuffer = res.map { it.second }.flatMap { it.buffer.array().toList() }.toDoubleArray() + val vBuffer = res.map { it.third }.flatMap { it.buffer.array().toList() }.toDoubleArray() + uBuffer.copyInto(matrixU.buffer.array()) + s.copyInto(matrixS.buffer.array()) + vBuffer.copyInto(matrixV.buffer.array()) +} diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 843707153..60f7f4a97 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -124,7 +124,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun svd1d() = DoubleLinearOpsTensorAlgebra { + fun testSVD1D() = DoubleLinearOpsTensorAlgebra { val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = svd1d(tensor2) @@ -135,7 +135,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun svd() = DoubleLinearOpsTensorAlgebra { + fun testSVD() = DoubleLinearOpsTensorAlgebra { val epsilon = 1e-10 fun test_tensor(tensor: DoubleTensor) { val svd = tensor.svd() From 45301d9172c5b02792288f2b50d1496be22f4c5a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 6 Apr 2021 11:15:47 +0300 Subject: [PATCH 171/393] Update build.yml Add timeout to build --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 25f2cfd0d..f39e12a12 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,7 @@ jobs: matrix: os: [ macOS-latest, windows-latest ] runs-on: ${{matrix.os}} + timeout-minutes: 30 steps: - name: Checkout the repo uses: actions/checkout@v2 From dcdc22dd9dddf8d3157fb51f1ee7b6bf226b3b8c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 6 Apr 2021 11:04:00 +0100 Subject: [PATCH 172/393] SVD test to be fixed --- .../kscience/kmath/tensors/TensorAlgebra.kt | 2 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 6 ++ .../kscience/kmath/tensors/core/utils.kt | 2 - .../core/TestDoubleLinearOpsAlgebra.kt | 65 +++++++++++-------- 4 files changed, 44 insertions(+), 31 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index d7c6eaefd..966806de1 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -40,7 +40,7 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.diag_embed.html public fun diagonalEmbedding( diagonalEntries: TensorType, - offset: Int = 0, dim1: Int = -2, dim2: Int = -1 + offset: Int = 0, dim1: Int = 0, dim2: Int = 1 ): TensorType } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index ab692c0f9..53063a066 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -362,6 +362,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra eps) { - return false - } - } - return true - } - @Test fun testDetLU() = DoubleLinearOpsTensorAlgebra { val tensor = fromArray( @@ -136,22 +121,46 @@ class TestDoubleLinearOpsTensorAlgebra { @Test fun testSVD() = DoubleLinearOpsTensorAlgebra { - val epsilon = 1e-10 - fun test_tensor(tensor: DoubleTensor) { - val svd = tensor.svd() + testSVDFor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) + testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) + } - val tensorSVD = svd.first - .dot( - diagonalEmbedding(svd.second, 0, 0, 1) - .dot(svd.third.transpose(0, 1)) - ) + @Test + fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { + val tensor = randNormal(intArrayOf(7, 5, 3), 0) + val (tensorU, tensorS, tensorV) = tensor.svd() + val tensorSVD = tensorU dot (diagonalEmbedding(tensorS,0,1,2) dot tensorV) + println(tensor.eq(tensorSVD)) + } - for ((x1, x2) in tensor.buffer.array() zip tensorSVD.buffer.array()) { - assertTrue { abs(x1 - x2) < epsilon } - } + +} + +private inline fun Double.epsEqual(other: Double, eps: Double = 1e-5): Boolean { + return abs(this - other) < eps +} + +private inline fun DoubleArray.epsEqual(other: DoubleArray, eps: Double = 1e-5): Boolean { + for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) { + if (abs(elem1 - elem2) > eps) { + return false } - test_tensor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) - test_tensor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) + } + return true +} +private inline fun DoubleLinearOpsTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10): Unit { + val svd = tensor.svd() + + val tensorSVD = svd.first + .dot( + diagonalEmbedding(svd.second, 0, 0, 1) + .dot(svd.third.transpose(0, 1)) + ) + + for ((x1, x2) in tensor.buffer.array() zip tensorSVD.buffer.array()) { + assertTrue { abs(x1 - x2) < epsilon } } } + + From 2bbe10e41c83e5ce44a920ad0a4c071b7d25f252 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 6 Apr 2021 11:41:41 +0100 Subject: [PATCH 173/393] SymEig test --- .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 0bd0ff5bd..29632e771 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.tensors.core import kotlin.math.abs +import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -125,12 +126,21 @@ class TestDoubleLinearOpsTensorAlgebra { testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } - @Test + @Test @Ignore fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { val tensor = randNormal(intArrayOf(7, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS,0,1,2) dot tensorV) - println(tensor.eq(tensorSVD)) + assertTrue(tensor.eq(tensorSVD)) + } + + @Test @Ignore + fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { + val tensor = randNormal(shape = intArrayOf(5, 2, 2), 0) + val tensorSigma = tensor + tensor.transpose(1, 2) + val (tensorS, tensorV) = tensorSigma.symEig() + val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS, 0,1,2) dot tensorV.transpose(1, 2)) + assertTrue(tensorSigma.eq(tensorSigmaCalc)) } From 174f6566e116b43e70622785c58291532b170369 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 6 Apr 2021 12:07:39 +0100 Subject: [PATCH 174/393] Negative indices --- .../kscience/kmath/tensors/TensorAlgebra.kt | 4 ++-- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 20 +++++++++++-------- .../tensors/core/TensorLinearStructure.kt | 3 +++ .../kscience/kmath/tensors/core/utils.kt | 12 ++++++++++- .../core/TestDoubleLinearOpsAlgebra.kt | 4 ++-- .../tensors/core/TestDoubleTensorAlgebra.kt | 4 ++-- 6 files changed, 32 insertions(+), 15 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 966806de1..8fd1cf2ed 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -28,7 +28,7 @@ public interface TensorAlgebra> { public operator fun TensorType.get(i: Int): TensorType //https://pytorch.org/docs/stable/generated/torch.transpose.html - public fun TensorType.transpose(i: Int, j: Int): TensorType + public fun TensorType.transpose(i: Int = -2, j: Int = -1): TensorType //https://pytorch.org/docs/stable/tensor_view.html public fun TensorType.view(shape: IntArray): TensorType @@ -40,7 +40,7 @@ public interface TensorAlgebra> { //https://pytorch.org/docs/stable/generated/torch.diag_embed.html public fun diagonalEmbedding( diagonalEntries: TensorType, - offset: Int = 0, dim1: Int = 0, dim2: Int = 1 + offset: Int = 0, dim1: Int = -2, dim2: Int = -1 ): TensorType } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 53063a066..870dbe8a7 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -198,19 +198,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra n || dim2 > n) { + if (d1 > n || d2 > n) { throw RuntimeException("Dimension out of range") } - var lessDim = dim1 - var greaterDim = dim2 + var lessDim = d1 + var greaterDim = d2 var realOffset = offset if (lessDim > greaterDim) { realOffset *= -1 diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt index 97ce29657..47745c2be 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt @@ -73,6 +73,9 @@ public class TensorLinearStructure(public val shape: IntArray) public val size: Int get() = shape.reduce(Int::times) + public val dim: Int + get() = shape.size + public fun indices(): Sequence = (0 until size).asSequence().map { index(it) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 5fd3cfd28..785b59ede 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -39,4 +39,14 @@ internal fun Buffer.array(): DoubleArray = when (this) { internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { val u = Random(seed) return (0 until n).map { sqrt(-2.0 * ln(u.nextDouble())) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() -} \ No newline at end of file +} + +internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { + val ii = n + i + check(ii >= 0) { + "Out of bound index $i for tensor of dim $n" + } + ii +} + +internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.linearStructure.dim, i) \ No newline at end of file diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 29632e771..56f9332f6 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -130,7 +130,7 @@ class TestDoubleLinearOpsTensorAlgebra { fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { val tensor = randNormal(intArrayOf(7, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() - val tensorSVD = tensorU dot (diagonalEmbedding(tensorS,0,1,2) dot tensorV) + val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV) assertTrue(tensor.eq(tensorSVD)) } @@ -139,7 +139,7 @@ class TestDoubleLinearOpsTensorAlgebra { val tensor = randNormal(shape = intArrayOf(5, 2, 2), 0) val tensorSigma = tensor + tensor.transpose(1, 2) val (tensorS, tensorV) = tensorSigma.symEig() - val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS, 0,1,2) dot tensorV.transpose(1, 2)) + val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose(1, 2)) assertTrue(tensorSigma.eq(tensorSigmaCalc)) } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 692db69af..fa7a8fd32 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -35,8 +35,8 @@ class TestDoubleTensorAlgebra { fun transpose1x2x3() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transpose(0, 1) - val res02 = tensor.transpose(0, 2) - val res12 = tensor.transpose(1, 2) + val res02 = tensor.transpose(-3, 2) + val res12 = tensor.transpose() assertTrue(res01.shape contentEquals intArrayOf(2, 1, 3)) assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) From 5bdc02d18cae34ea05e4931a4714ddb63f2950d5 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 6 Apr 2021 17:17:43 +0300 Subject: [PATCH 175/393] fix for #272 --- CHANGELOG.md | 1 + build.gradle.kts | 2 +- .../kscience/kmath/kotlingrad/DifferentiableMstExpression.kt | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4d3b93e9..fdace591c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Field extends ScaleOperations - Basic integration API - Basic MPP distributions and samplers +- bindSymbolOrNull ### Changed - Exponential operations merged with hyperbolic functions diff --git a/build.gradle.kts b/build.gradle.kts index cc863a957..59e93e67f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,7 +18,7 @@ allprojects { } group = "space.kscience" - version = "0.3.0-dev-4" + version = "0.3.0-dev-5" } subprojects { diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt index d5b55e031..ab3547cda 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -5,7 +5,6 @@ import space.kscience.kmath.ast.MST import space.kscience.kmath.ast.MstAlgebra import space.kscience.kmath.ast.interpret import space.kscience.kmath.expressions.DifferentiableExpression -import space.kscience.kmath.expressions.Expression import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.NumericAlgebra @@ -22,7 +21,7 @@ import space.kscience.kmath.operations.NumericAlgebra public class DifferentiableMstExpression>( public val algebra: A, public val mst: MST, -) : DifferentiableExpression> { +) : DifferentiableExpression> { public override fun invoke(arguments: Map): T = mst.interpret(algebra, arguments) From 31460df721fccef597a62a48d0bbac92e4f1ae05 Mon Sep 17 00:00:00 2001 From: darksnake Date: Wed, 7 Apr 2021 14:14:22 +0300 Subject: [PATCH 176/393] GaussianSampler inherits Blocking Sampler --- .../kotlin/space/kscience/kmath/samplers/GaussianSampler.kt | 3 +-- .../space/kscience/kmath/stat/CommonsDistributionsTest.kt | 6 ++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt index 26047830c..237da920c 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt @@ -3,7 +3,6 @@ package space.kscience.kmath.samplers import space.kscience.kmath.chains.BlockingDoubleChain import space.kscience.kmath.chains.map import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.stat.Sampler /** * Sampling from a Gaussian distribution with given mean and standard deviation. @@ -18,7 +17,7 @@ public class GaussianSampler( public val mean: Double, public val standardDeviation: Double, private val normalized: NormalizedGaussianSampler = BoxMullerSampler -) : Sampler { +) : BlockingDoubleSampler { init { require(standardDeviation > 0.0) { "standard deviation is not strictly positive: $standardDeviation" } diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt index c6b9cb17a..976020f08 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -18,10 +18,12 @@ internal class CommonsDistributionsTest { } @Test - fun testNormalDistributionBlocking() = runBlocking { + fun testNormalDistributionBlocking() { val distribution = GaussianSampler(7.0, 2.0) val generator = RandomGenerator.default(1) val sample = distribution.sample(generator).nextBufferBlocking(1000) - Assertions.assertEquals(7.0, Mean.double(sample), 0.2) + runBlocking { + Assertions.assertEquals(7.0, Mean.double(sample), 0.2) + } } } From 74dfca4e2e265a17bcba9b4d968a56ddd5d07ad9 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 7 Apr 2021 15:11:00 +0100 Subject: [PATCH 177/393] Using kmath-stat for random normals --- .../kotlin/space/kscience/kmath/tensors/core/utils.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 785b59ede..c99f9d156 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.samplers.GaussianSampler +import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.* -import kotlin.random.Random -import kotlin.math.* /** * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. @@ -37,8 +37,9 @@ internal fun Buffer.array(): DoubleArray = when (this) { } internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { - val u = Random(seed) - return (0 until n).map { sqrt(-2.0 * ln(u.nextDouble())) * cos(2.0 * PI * u.nextDouble()) }.toDoubleArray() + val distribution = GaussianSampler(0.0, 1.0) + val generator = RandomGenerator.default(seed) + return distribution.sample(generator).nextBufferBlocking(n).toDoubleArray() } internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { From ea4d6618b4c2c7ecc22f82c4376b2b06904ff7c2 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 8 Apr 2021 23:58:44 +0300 Subject: [PATCH 178/393] fix bugs in svd --- .../tensors/core/DoubleLinearOpsTensorAlgebra.kt | 14 ++++++++++---- .../kscience/kmath/tensors/core/linutils.kt | 16 +++++++++++----- .../space/kscience/kmath/tensors/core/utils.kt | 7 +++++++ .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 4 ++-- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 7db812d9d..83a41b80d 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -96,14 +96,20 @@ public class DoubleLinearOpsTensorAlgebra : val size = this.shape.size val commonShape = this.shape.sliceArray(0 until size - 2) val (n, m) = this.shape.sliceArray(size - 2 until size) - val resU = zeros(commonShape + intArrayOf(n, min(n, m))) + val resU = zeros(commonShape + intArrayOf(min(n, m), n)) val resS = zeros(commonShape + intArrayOf(min(n, m))) val resV = zeros(commonShape + intArrayOf(min(n, m), m)) for ((matrix, USV) in this.matrixSequence() - .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) - svdHelper(matrix.asTensor(), USV, m, n) - return Triple(resU, resS, resV.transpose(size - 2, size - 1)) + .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) { + val size = matrix.shape.reduce { acc, i -> acc * i } + val curMatrix = DoubleTensor( + matrix.shape, + matrix.buffer.array().slice(matrix.bufferStart until matrix.bufferStart + size).toDoubleArray() + ) + svdHelper(curMatrix, USV, m, n) + } + return Triple(resU.transpose(size - 2, size - 1), resS, resV) } override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index e1d5c1819..1bdfee2d5 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -225,10 +225,10 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: val b: DoubleTensor if (n > m) { b = a.transpose(0, 1).dot(a) - v = DoubleTensor(intArrayOf(m), getRandomNormals(m, 0)) + v = DoubleTensor(intArrayOf(m), getRandomUnitVector(m, 0)) } else { b = a.dot(a.transpose(0, 1)) - v = DoubleTensor(intArrayOf(n), getRandomNormals(n, 0)) + v = DoubleTensor(intArrayOf(n), getRandomUnitVector(n, 0)) } var lastV: DoubleTensor @@ -284,7 +284,13 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( val s = res.map { it.first }.toDoubleArray() val uBuffer = res.map { it.second }.flatMap { it.buffer.array().toList() }.toDoubleArray() val vBuffer = res.map { it.third }.flatMap { it.buffer.array().toList() }.toDoubleArray() - uBuffer.copyInto(matrixU.buffer.array()) - s.copyInto(matrixS.buffer.array()) - vBuffer.copyInto(matrixV.buffer.array()) + for (i in uBuffer.indices) { + matrixU.buffer.array()[matrixU.bufferStart + i] = uBuffer[i] + } + for (i in s.indices) { + matrixS.buffer.array()[matrixS.bufferStart + i] = s[i] + } + for (i in vBuffer.indices) { + matrixV.buffer.array()[matrixV.bufferStart + i] = vBuffer[i] + } } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index c99f9d156..392abd1c2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -3,6 +3,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.* +import kotlin.math.sqrt /** * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. @@ -42,6 +43,12 @@ internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { return distribution.sample(generator).nextBufferBlocking(n).toDoubleArray() } +internal inline fun getRandomUnitVector(n: Int, seed: Long): DoubleArray { + val unnorm = getRandomNormals(n, seed) + val norm = sqrt(unnorm.map { it * it }.sum()) + return unnorm.map { it / norm }.toDoubleArray() +} + internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { val ii = n + i check(ii >= 0) { diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 56f9332f6..35390968e 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -126,9 +126,9 @@ class TestDoubleLinearOpsTensorAlgebra { testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } - @Test @Ignore + @Test fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { - val tensor = randNormal(intArrayOf(7, 5, 3), 0) + val tensor = randNormal(intArrayOf(1, 15, 4, 7, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV) assertTrue(tensor.eq(tensorSVD)) From a09a1c7adc73615d46b4fa5d1611c3a694b8d5a8 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 07:33:25 +0100 Subject: [PATCH 179/393] Fixed tests --- .../core/DoubleLinearOpsTensorAlgebra.kt | 6 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 7 --- .../kscience/kmath/tensors/core/checks.kt | 3 +- .../core/TestDoubleLinearOpsAlgebra.kt | 63 ++++++++----------- 4 files changed, 31 insertions(+), 48 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 83a41b80d..916361abe 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -93,7 +93,7 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.svd(): Triple { - val size = this.shape.size + val size = this.linearStructure.dim val commonShape = this.shape.sliceArray(0 until size - 2) val (n, m) = this.shape.sliceArray(size - 2 until size) val resU = zeros(commonShape + intArrayOf(min(n, m), n)) @@ -109,11 +109,11 @@ public class DoubleLinearOpsTensorAlgebra : ) svdHelper(curMatrix, USV, m, n) } - return Triple(resU.transpose(size - 2, size - 1), resS, resV) + return Triple(resU.transpose(), resS, resV.transpose()) } override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { - TODO("ANDREI") + TODO() } public fun DoubleTensor.detLU(): DoubleTensor { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 870dbe8a7..8f355dd3d 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -339,19 +339,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra abs(x - y) < delta } - } - public fun DoubleTensor.eq(other: DoubleTensor, delta: Double): Boolean { return this.eq(other) { x, y -> abs(x - y) < delta } } public fun DoubleTensor.eq(other: DoubleTensor): Boolean = this.eq(other, 1e-5) - public fun DoubleTensor.contentEquals(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean = - this.eq(other, eqFunction) - private fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { checkShapesCompatible(this, other) val n = this.linearStructure.size diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 247ed3913..f994324ff 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -56,4 +56,5 @@ internal inline fun , check(shape[n - 1] == shape[n - 2]) { "Tensor must be batches of square matrices, but they are ${shape[n - 1]} by ${shape[n - 1]} matrices" } -} \ No newline at end of file +} + diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 35390968e..df896bace 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -20,15 +20,17 @@ class TestDoubleLinearOpsTensorAlgebra { ) ) - val expectedShape = intArrayOf(2, 1) - val expectedBuffer = doubleArrayOf( - -1.0, - -7.0 + val expectedTensor = fromArray( + intArrayOf(2, 1), + doubleArrayOf( + -1.0, + -7.0 + ) ) val detTensor = tensor.detLU() - assertTrue { detTensor.shape contentEquals expectedShape } - assertTrue { detTensor.buffer.array().epsEqual(expectedBuffer) } + assertTrue(detTensor.eq(expectedTensor)) + } @Test @@ -43,17 +45,17 @@ class TestDoubleLinearOpsTensorAlgebra { ) ) - val expectedShape = intArrayOf(2, 2, 2) - val expectedBuffer = doubleArrayOf( - 1.0, 0.0, - 0.0, 0.5, - 0.0, 1.0, - 1.0, -1.0 + val expectedTensor = fromArray( + intArrayOf(2, 2, 2), doubleArrayOf( + 1.0, 0.0, + 0.0, 0.5, + 0.0, 1.0, + 1.0, -1.0 + ) ) val invTensor = tensor.invLU() - assertTrue { invTensor.shape contentEquals expectedShape } - assertTrue { invTensor.buffer.array().epsEqual(expectedBuffer) } + assertTrue(invTensor.eq(expectedTensor)) } @Test @@ -80,7 +82,7 @@ class TestDoubleLinearOpsTensorAlgebra { assertTrue { q.shape contentEquals shape } assertTrue { r.shape contentEquals shape } - assertTrue { q.dot(r).buffer.array().epsEqual(buffer) } + assertTrue((q dot r).eq(tensor)) //todo check orthogonality/upper triang. } @@ -106,7 +108,7 @@ class TestDoubleLinearOpsTensorAlgebra { assertTrue { l.shape contentEquals shape } assertTrue { u.shape contentEquals shape } - assertTrue { p.dot(tensor).buffer.array().epsEqual(l.dot(u).buffer.array()) } + assertTrue((p dot tensor).eq(l dot u)) } @Test @@ -116,8 +118,8 @@ class TestDoubleLinearOpsTensorAlgebra { val res = svd1d(tensor2) assertTrue(res.shape contentEquals intArrayOf(2)) - assertTrue { abs(abs(res.buffer.array()[res.bufferStart]) - 0.386) < 0.01} - assertTrue { abs(abs(res.buffer.array()[res.bufferStart + 1]) - 0.922) < 0.01} + assertTrue { abs(abs(res.buffer.array()[res.bufferStart]) - 0.386) < 0.01 } + assertTrue { abs(abs(res.buffer.array()[res.bufferStart + 1]) - 0.922) < 0.01 } } @Test @@ -130,11 +132,12 @@ class TestDoubleLinearOpsTensorAlgebra { fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { val tensor = randNormal(intArrayOf(1, 15, 4, 7, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() - val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV) + val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) assertTrue(tensor.eq(tensorSVD)) } - @Test @Ignore + @Test + @Ignore fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { val tensor = randNormal(shape = intArrayOf(5, 2, 2), 0) val tensorSigma = tensor + tensor.transpose(1, 2) @@ -146,31 +149,17 @@ class TestDoubleLinearOpsTensorAlgebra { } -private inline fun Double.epsEqual(other: Double, eps: Double = 1e-5): Boolean { - return abs(this - other) < eps -} - -private inline fun DoubleArray.epsEqual(other: DoubleArray, eps: Double = 1e-5): Boolean { - for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) { - if (abs(elem1 - elem2) > eps) { - return false - } - } - return true -} private inline fun DoubleLinearOpsTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10): Unit { val svd = tensor.svd() val tensorSVD = svd.first .dot( - diagonalEmbedding(svd.second, 0, 0, 1) - .dot(svd.third.transpose(0, 1)) + diagonalEmbedding(svd.second) + .dot(svd.third.transpose()) ) - for ((x1, x2) in tensor.buffer.array() zip tensorSVD.buffer.array()) { - assertTrue { abs(x1 - x2) < epsilon } - } + assertTrue(tensor.eq(tensorSVD, epsilon)) } From 8c1131dd5818f75b1b0eb9e0b3ef23f12f6a7c07 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 08:03:47 +0100 Subject: [PATCH 180/393] Approaching SymEig through SVD --- .../kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 6 ++++-- .../kotlin/space/kscience/kmath/tensors/core/checks.kt | 4 ++++ .../kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 916361abe..43502e79a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -67,7 +67,7 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.cholesky(): DoubleTensor { - // todo checks + checkSymmetric(this) checkSquareMatrix(shape) val n = shape.last() @@ -113,7 +113,9 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { - TODO() + checkSymmetric(this) + val svd = this.svd() + TODO("U might have some columns negative to V") } public fun DoubleTensor.detLU(): DoubleTensor { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index f994324ff..1f70eb300 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -58,3 +58,7 @@ internal inline fun , } } +internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor): Unit = + check(tensor.eq(tensor.transpose())){ + "Tensor is not symmetric about the last 2 dimensions" + } \ No newline at end of file diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index df896bace..cc127b5a7 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -140,9 +140,9 @@ class TestDoubleLinearOpsTensorAlgebra { @Ignore fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { val tensor = randNormal(shape = intArrayOf(5, 2, 2), 0) - val tensorSigma = tensor + tensor.transpose(1, 2) + val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() - val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose(1, 2)) + val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) assertTrue(tensorSigma.eq(tensorSigmaCalc)) } From 5d8b42da906fec8c5450a4babf461a4873a8aee9 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 08:29:08 +0100 Subject: [PATCH 181/393] minor corrections to linear stuff --- .../kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 43502e79a..4e67e1d16 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -67,6 +67,7 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.cholesky(): DoubleTensor { + //positive definite check checkSymmetric(this) checkSquareMatrix(shape) @@ -114,8 +115,7 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { checkSymmetric(this) - val svd = this.svd() - TODO("U might have some columns negative to V") + TODO("maybe use SVD") } public fun DoubleTensor.detLU(): DoubleTensor { From e4dbabc30f5a740deae2055c33c982637463d85e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 08:32:03 +0100 Subject: [PATCH 182/393] more infor --- .../kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 4e67e1d16..7d99b7b51 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -115,6 +115,8 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { checkSymmetric(this) + //http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html + //see the last point TODO("maybe use SVD") } From 3f0dff3ce9f830f6c04ac72346eb6053c61ae0bf Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 09:18:00 +0100 Subject: [PATCH 183/393] Approximate spectral decomposition for symmetric matrices based on SVD --- .../tensors/core/DoubleLinearOpsTensorAlgebra.kt | 11 ++++++++--- .../kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 6 +++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 7d99b7b51..268f2fe55 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -3,8 +3,10 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.structures.toList import kotlin.math.abs import kotlin.math.min +import kotlin.math.sign public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -113,11 +115,14 @@ public class DoubleLinearOpsTensorAlgebra : return Triple(resU.transpose(), resS, resV.transpose()) } + //http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { checkSymmetric(this) - //http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html - //see the last point - TODO("maybe use SVD") + val (u, s, v) = this.svd() + val shp = s.shape + intArrayOf(1) + val utv = (u.transpose() dot v).map { if (abs(it) < 0.99) 0.0 else sign(it) } + val eig = (utv dot s.view(shp)).view(s.shape) + return Pair(eig, v) } public fun DoubleTensor.detLU(): DoubleTensor { diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index cc127b5a7..c96fcb1c0 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.structures.toList import kotlin.math.abs import kotlin.test.Ignore import kotlin.test.Test @@ -137,13 +138,12 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - @Ignore fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { - val tensor = randNormal(shape = intArrayOf(5, 2, 2), 0) + val tensor = randNormal(shape = intArrayOf(5, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) - assertTrue(tensorSigma.eq(tensorSigmaCalc)) + assertTrue(tensorSigma.eq(tensorSigmaCalc, 0.01)) } From fe8579180d8ebe92b8ba2a41a74d5932d90694a9 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 09:56:37 +0100 Subject: [PATCH 184/393] Open epsilon to client to control numerical precision for power methods --- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 4 ++-- .../core/DoubleLinearOpsTensorAlgebra.kt | 17 +++++++++++------ .../space/kscience/kmath/tensors/core/checks.kt | 6 +++--- .../kscience/kmath/tensors/core/linutils.kt | 6 +++--- .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 2 +- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index d980c510f..87c459f35 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.tensors -public interface LinearOpsTensorAlgebra, IndexTensorType: TensorStructure> : +public interface LinearOpsTensorAlgebra, IndexTensorType : TensorStructure> : TensorPartialDivisionAlgebra { //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det @@ -26,6 +26,6 @@ public interface LinearOpsTensorAlgebra, Inde public fun TensorType.svd(): Triple //https://pytorch.org/docs/stable/generated/torch.symeig.html - public fun TensorType.symEig(eigenvectors: Boolean = true): Pair + public fun TensorType.symEig(): Pair } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 268f2fe55..95b668917 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -94,8 +94,10 @@ public class DoubleLinearOpsTensorAlgebra : return qTensor to rTensor } + override fun DoubleTensor.svd(): Triple = + svd(epsilon = 1e-10) - override fun DoubleTensor.svd(): Triple { + public fun DoubleTensor.svd(epsilon: Double): Triple { val size = this.linearStructure.dim val commonShape = this.shape.sliceArray(0 until size - 2) val (n, m) = this.shape.sliceArray(size - 2 until size) @@ -110,17 +112,20 @@ public class DoubleLinearOpsTensorAlgebra : matrix.shape, matrix.buffer.array().slice(matrix.bufferStart until matrix.bufferStart + size).toDoubleArray() ) - svdHelper(curMatrix, USV, m, n) + svdHelper(curMatrix, USV, m, n, epsilon) } return Triple(resU.transpose(), resS, resV.transpose()) } + override fun DoubleTensor.symEig(): Pair = + symEig(epsilon = 1e-15) + //http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html - override fun DoubleTensor.symEig(eigenvectors: Boolean): Pair { - checkSymmetric(this) - val (u, s, v) = this.svd() + public fun DoubleTensor.symEig(epsilon: Double): Pair { + checkSymmetric(this, epsilon) + val (u, s, v) = this.svd(epsilon) val shp = s.shape + intArrayOf(1) - val utv = (u.transpose() dot v).map { if (abs(it) < 0.99) 0.0 else sign(it) } + val utv = (u.transpose() dot v).map { if (abs(it) < 0.9) 0.0 else sign(it) } val eig = (utv dot s.view(shp)).view(s.shape) return Pair(eig, v) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 1f70eb300..1dde2ea56 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -58,7 +58,7 @@ internal inline fun , } } -internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor): Unit = - check(tensor.eq(tensor.transpose())){ - "Tensor is not symmetric about the last 2 dimensions" +internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor, epsilon: Double = 1e-6): Unit = + check(tensor.eq(tensor.transpose(), epsilon)) { + "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index 1bdfee2d5..685c16a1b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -246,7 +246,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( matrix: DoubleTensor, USV: Pair, Pair, BufferedTensor>>, - m: Int, n: Int + m: Int, n: Int, epsilon: Double ): Unit { val res = ArrayList>(0) val (matrixU, SV) = USV @@ -267,12 +267,12 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( var u: DoubleTensor var norm: Double if (n > m) { - v = svd1d(a) + v = svd1d(a, epsilon) u = matrix.dot(v) norm = DoubleAnalyticTensorAlgebra { (u dot u).sqrt().value() } u = u.times(1.0 / norm) } else { - u = svd1d(a) + u = svd1d(a, epsilon) v = matrix.transpose(0, 1).dot(u) norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } v = v.times(1.0 / norm) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index c96fcb1c0..0997a9b86 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -143,7 +143,7 @@ class TestDoubleLinearOpsTensorAlgebra { val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) - assertTrue(tensorSigma.eq(tensorSigmaCalc, 0.01)) + assertTrue(tensorSigma.eq(tensorSigmaCalc)) } From a692412cff00241031258e37e1f7c2ad151518f4 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 10:08:55 +0100 Subject: [PATCH 185/393] Safer cleaner for symeig --- .../tensors/core/DoubleLinearOpsTensorAlgebra.kt | 10 ++++++---- .../space/kscience/kmath/tensors/core/linutils.kt | 12 ++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 95b668917..c26046e37 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -3,10 +3,8 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D -import space.kscience.kmath.structures.toList -import kotlin.math.abs import kotlin.math.min -import kotlin.math.sign + public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, @@ -125,7 +123,11 @@ public class DoubleLinearOpsTensorAlgebra : checkSymmetric(this, epsilon) val (u, s, v) = this.svd(epsilon) val shp = s.shape + intArrayOf(1) - val utv = (u.transpose() dot v).map { if (abs(it) < 0.9) 0.0 else sign(it) } + val utv = u.transpose() dot v + val n = s.shape.last() + for( matrix in utv.matrixSequence()) + cleanSymHelper(matrix.as2D(),n) + val eig = (utv dot s.view(shp)).view(s.shape) return Pair(eig, v) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index 685c16a1b..b3cfc1092 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -6,6 +6,7 @@ import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import kotlin.math.abs import kotlin.math.min +import kotlin.math.sign import kotlin.math.sqrt @@ -294,3 +295,14 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( matrixV.buffer.array()[matrixV.bufferStart + i] = vBuffer[i] } } + +internal inline fun cleanSymHelper(matrix: MutableStructure2D, n: Int): Unit { + for (i in 0 until n) + for (j in 0 until n) { + if (i == j) { + matrix[i, j] = sign(matrix[i, j]) + } else { + matrix[i, j] = 0.0 + } + } +} From 1e8da7a87bcc00830338d66f8d68fb2dfda7698b Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 10:53:36 +0100 Subject: [PATCH 186/393] Cholesky decomp tests and checks - det to be fixed --- .../tensors/core/DoubleLinearOpsTensorAlgebra.kt | 3 ++- .../space/kscience/kmath/tensors/core/checks.kt | 9 ++++++++- .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 13 +++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index c26046e37..4d6d14764 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -67,9 +67,10 @@ public class DoubleLinearOpsTensorAlgebra : } override fun DoubleTensor.cholesky(): DoubleTensor { - //positive definite check checkSymmetric(this) checkSquareMatrix(shape) + //TODO("Andrei the det routine has bugs") + //checkPositiveDefinite(this) val n = shape.last() val lTensor = zeroesLike() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 1dde2ea56..8dbf9eb81 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -61,4 +61,11 @@ internal inline fun , internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor, epsilon: Double = 1e-6): Unit = check(tensor.eq(tensor.transpose(), epsilon)) { "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" - } \ No newline at end of file + } + +internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor): Unit { + for( mat in tensor.matrixSequence()) + check(mat.asTensor().detLU().value() > 0.0){ + "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" + } +} \ No newline at end of file diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 0997a9b86..2914b216b 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -112,6 +112,19 @@ class TestDoubleLinearOpsTensorAlgebra { assertTrue((p dot tensor).eq(l dot u)) } + @Test + fun testCholesky() = DoubleLinearOpsTensorAlgebra { + val tensor = randNormal(intArrayOf(2, 5, 5), 0) + val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( + fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) + ) + //checkPositiveDefinite(sigma) sigma must be positive definite + val low = sigma.cholesky() + val sigmChol = low dot low.transpose() + assertTrue(sigma.eq(sigmChol)) + + } + @Test fun testSVD1D() = DoubleLinearOpsTensorAlgebra { val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) From b51427d2abb401d1402eebd7bf61e93bca47f3a2 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 12:26:03 +0100 Subject: [PATCH 187/393] test to fix determinant --- .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 2914b216b..37caf88fe 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -34,6 +34,19 @@ class TestDoubleLinearOpsTensorAlgebra { } + @Test + fun testDet() = DoubleLinearOpsTensorAlgebra { + val m = fromArray( + intArrayOf(3, 3), doubleArrayOf( + 2.1843, 1.4391, -0.4845, + 1.4391, 1.7772, 0.4055, + -0.4845, 0.4055, 0.7519 + ) + ) + println(m.det().value()) + println(0.0197) //expected value + } + @Test fun testInvLU() = DoubleLinearOpsTensorAlgebra { val tensor = fromArray( From 75783bcb038d1649f5587a15e906d9450fce5c8c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 9 Apr 2021 14:06:44 +0100 Subject: [PATCH 188/393] some todos --- .../kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 4d6d14764..82f63dd40 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -154,6 +154,7 @@ public class DoubleLinearOpsTensorAlgebra : } public fun DoubleTensor.invLU(): DoubleTensor { + //TODO("Andrei the det is non-zero") val (luTensor, pivotsTensor) = lu() val invTensor = luTensor.zeroesLike() From acb4052fe46965c830d65d0fedc45f653077d5b2 Mon Sep 17 00:00:00 2001 From: darksnake Date: Sat, 10 Apr 2021 15:20:09 +0300 Subject: [PATCH 189/393] Migrate to gradle 7.0 and suspend-inline bug --- build.gradle.kts | 10 ++++++---- examples/build.gradle.kts | 5 ++++- gradle/wrapper/gradle-wrapper.properties | 2 +- .../kscience/kmath/operations/algebraExtensions.kt | 8 ++++++-- settings.gradle.kts | 4 ++-- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 59e93e67f..40ce768cd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.dokka.gradle.DokkaTask -import ru.mipt.npm.gradle.KSciencePublishingPlugin import java.net.URL plugins { @@ -13,16 +12,19 @@ allprojects { maven("https://dl.bintray.com/egor-bogomolov/astminer/") maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://jitpack.io") - maven("http://logicrunch.research.it.uu.se/maven/") + maven{ + setUrl("http://logicrunch.research.it.uu.se/maven/") + isAllowInsecureProtocol = true + } mavenCentral() } group = "space.kscience" - version = "0.3.0-dev-5" + version = "0.3.0-dev-6" } subprojects { - if (name.startsWith("kmath")) apply() + if (name.startsWith("kmath")) apply() afterEvaluate { tasks.withType { diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index a48b4d0d9..5968f118c 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -20,7 +20,10 @@ repositories { maven("https://dl.bintray.com/mipt-npm/dev") maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://jitpack.io") - maven("http://logicrunch.research.it.uu.se/maven/") + maven{ + setUrl("http://logicrunch.research.it.uu.se/maven/") + isAllowInsecureProtocol = true + } mavenCentral() } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 442d9132e..f371643ee 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index b927655e3..93ce92f37 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -7,7 +7,9 @@ package space.kscience.kmath.operations * @param data the iterable to sum up. * @return the sum. */ -public fun Group.sum(data: Iterable): T = data.fold(zero) { left, right -> add(left, right) } +public fun Group.sum(data: Iterable): T = data.fold(zero) { left, right -> + add(left, right) +} /** * Returns the sum of all elements in the sequence in this [Group]. @@ -16,7 +18,9 @@ public fun Group.sum(data: Iterable): T = data.fold(zero) { left, righ * @param data the sequence to sum up. * @return the sum. */ -public fun Group.sum(data: Sequence): T = data.fold(zero) { left, right -> add(left, right) } +public fun Group.sum(data: Sequence): T = data.fold(zero) { left, right -> + add(left, right) +} /** * Returns an average value of elements in the iterable in this [Group]. diff --git a/settings.gradle.kts b/settings.gradle.kts index 4467d5ed6..e419ac0e2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,8 +7,8 @@ pluginManagement { maven("https://dl.bintray.com/kotlin/kotlinx") } - val toolsVersion = "0.9.3" - val kotlinVersion = "1.4.32" + val toolsVersion = "0.9.5" + val kotlinVersion = "1.5.0-M2" plugins { id("kotlinx.benchmark") version "0.2.0-dev-20" From 4abd0bdb6f2e1ea8f7df878b257ec93b2fdf3554 Mon Sep 17 00:00:00 2001 From: darksnake Date: Sat, 10 Apr 2021 16:31:08 +0300 Subject: [PATCH 190/393] Migrate to gradle 7.0 and suspend-inline bug --- gradle/wrapper/gradle-wrapper.properties | 2 +- .../space/kscience/kmath/stat/CommonsDistributionsTest.kt | 2 +- settings.gradle.kts | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f371643ee..442d9132e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt index 976020f08..dca0242fc 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -13,7 +13,7 @@ internal class CommonsDistributionsTest { fun testNormalDistributionSuspend() = runBlocking { val distribution = GaussianSampler(7.0, 2.0) val generator = RandomGenerator.default(1) - val sample = distribution.sample(generator).take(1000).toList().asBuffer() + val sample = distribution.sample(generator).take(1000).toList().toDoubleArray().asBuffer() Assertions.assertEquals(7.0, Mean.double(sample), 0.2) } diff --git a/settings.gradle.kts b/settings.gradle.kts index e419ac0e2..1f62b1388 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,6 +17,7 @@ pluginManagement { id("ru.mipt.npm.gradle.jvm") version toolsVersion id("ru.mipt.npm.gradle.publish") version toolsVersion kotlin("jvm") version kotlinVersion + kotlin("multiplatform") version kotlinVersion kotlin("plugin.allopen") version kotlinVersion } } From 000c79d42f6d61d676360c0c6aabf338de8bdc43 Mon Sep 17 00:00:00 2001 From: darksnake Date: Sat, 10 Apr 2021 17:15:15 +0300 Subject: [PATCH 191/393] Simplify test --- .../space/kscience/kmath/stat/CommonsDistributionsTest.kt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt index dca0242fc..e175c76ee 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -1,24 +1,21 @@ package space.kscience.kmath.stat -import kotlinx.coroutines.flow.take -import kotlinx.coroutines.flow.toList import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import space.kscience.kmath.samplers.GaussianSampler -import space.kscience.kmath.structures.asBuffer internal class CommonsDistributionsTest { @Test fun testNormalDistributionSuspend() = runBlocking { val distribution = GaussianSampler(7.0, 2.0) val generator = RandomGenerator.default(1) - val sample = distribution.sample(generator).take(1000).toList().toDoubleArray().asBuffer() + val sample = distribution.sample(generator).nextBuffer(1000) Assertions.assertEquals(7.0, Mean.double(sample), 0.2) } @Test - fun testNormalDistributionBlocking() { + fun testNormalDistributionBlocking() { val distribution = GaussianSampler(7.0, 2.0) val generator = RandomGenerator.default(1) val sample = distribution.sample(generator).nextBufferBlocking(1000) From ce4dcb63b045a8e16617b16fcbec76cec910bc45 Mon Sep 17 00:00:00 2001 From: darksnake Date: Sat, 10 Apr 2021 17:29:36 +0300 Subject: [PATCH 192/393] Roll-back to 0.9.4 plugin --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 1f62b1388..38a4d86ff 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,7 +7,7 @@ pluginManagement { maven("https://dl.bintray.com/kotlin/kotlinx") } - val toolsVersion = "0.9.5" + val toolsVersion = "0.9.4" val kotlinVersion = "1.5.0-M2" plugins { From 6cea5742e88df5fdb811d8a097f2d93d37a111d2 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 14 Apr 2021 12:40:26 +0300 Subject: [PATCH 193/393] Blocking statistics. Move MST to core --- CHANGELOG.md | 1 + README.md | 6 +- examples/build.gradle.kts | 4 +- .../ExpressionsInterpretersBenchmark.kt | 6 +- .../space/kscience/kmath/ast/expressions.kt | 2 + .../kmath/stat/DistributionBenchmark.kt | 6 +- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- kmath-ast/README.md | 6 +- kmath-ast/build.gradle.kts | 7 +- .../kmath/ast/rendering/MathRenderer.kt | 2 +- .../kscience/kmath/ast/rendering/features.kt | 2 +- .../space/kscisnce/kmath/ast/InterpretTest.kt | 4 +- .../space/kscience/kmath/estree/estree.kt | 17 +- .../TestESTreeConsistencyWithInterpreter.kt | 2 +- .../estree/TestESTreeOperationsSupport.kt | 2 +- .../kmath/estree/TestESTreeSpecialization.kt | 2 +- .../kmath/estree/TestESTreeVariables.kt | 2 +- .../kotlin/space/kscience/kmath/asm/asm.kt | 18 +- .../kscience/kmath/asm/internal/AsmBuilder.kt | 2 +- .../kmath/asm/internal/codegenUtils.kt | 2 +- .../kotlin/space/kscience/kmath/ast/parser.kt | 1 + .../asm/TestAsmConsistencyWithInterpreter.kt | 2 +- .../kmath/asm/TestAsmOperationsSupport.kt | 6 +- .../kmath/asm/TestAsmSpecialization.kt | 2 +- .../kscience/kmath/asm/TestAsmVariables.kt | 2 +- .../kmath/ast/ParserPrecedenceTest.kt | 1 + .../space/kscience/kmath/ast/ParserTest.kt | 3 + .../kmath/ast/rendering/TestFeatures.kt | 2 +- .../kscience/kmath/ast/rendering/TestLatex.kt | 2 +- .../kmath/ast/rendering/TestMathML.kt | 2 +- .../kscience/kmath/ast/rendering/TestUtils.kt | 2 +- kmath-commons/build.gradle.kts | 3 +- kmath-complex/build.gradle.kts | 7 +- kmath-core/api/kmath-core.api | 326 ++++++++++++++++++ kmath-core/build.gradle.kts | 7 +- .../space/kscience/kmath/expressions}/MST.kt | 3 +- .../kscience/kmath/expressions}/MstAlgebra.kt | 2 +- kmath-coroutines/build.gradle.kts | 4 +- kmath-dimensions/build.gradle.kts | 3 +- kmath-ejml/build.gradle.kts | 7 +- kmath-for-real/build.gradle.kts | 3 +- kmath-functions/build.gradle.kts | 3 +- .../kmath/integration/UnivariateIntegrand.kt | 4 +- .../kmath/interpolation/LoessInterpolator.kt | 296 ---------------- kmath-geometry/build.gradle.kts | 4 +- kmath-histograms/build.gradle.kts | 3 +- kmath-kotlingrad/build.gradle.kts | 3 +- .../kotlingrad/DifferentiableMstExpression.kt | 6 +- .../kmath/kotlingrad/ScalarsAdapters.kt | 8 +- .../kmath/kotlingrad/AdaptingTests.kt | 2 +- kmath-memory/build.gradle.kts | 5 +- kmath-nd4j/build.gradle.kts | 7 +- kmath-stat/build.gradle.kts | 5 +- .../kotlin/space/kscience/kmath/stat/Mean.kt | 45 +++ .../space/kscience/kmath/stat/Median.kt | 16 + .../space/kscience/kmath/stat/Statistic.kt | 52 +-- .../kmath/stat/CommonsDistributionsTest.kt | 11 +- .../kscience/kmath/stat/StatisticTest.kt | 14 +- kmath-viktor/build.gradle.kts | 3 +- settings.gradle.kts | 11 +- 61 files changed, 527 insertions(+), 458 deletions(-) rename {kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast => kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions}/MST.kt (98%) rename {kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast => kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions}/MstAlgebra.kt (99%) delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LoessInterpolator.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Median.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index fdace591c..c7fe7eed2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - DataSets are moved from functions to core - Redesign advanced Chain API - Redesign MST. Remove MSTExpression. +- Move MST to core ### Deprecated diff --git a/README.md b/README.md index 7b78d4531..bacf77bd5 100644 --- a/README.md +++ b/README.md @@ -87,9 +87,9 @@ KMath is a modular library. Different modules provide different features with di > > **Features:** > - [expression-language](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser -> - [mst](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation -> - [mst-building](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure -> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter +> - [mst](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation +> - [mst-building](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt) : MST building algebraic structure +> - [mst-interpreter](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt) : MST interpreter > - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler > - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 5968f118c..3fc2ec7f0 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { kotlin("jvm") kotlin("plugin.allopen") - id("kotlinx.benchmark") + id("org.jetbrains.kotlinx.benchmark") } allOpen.annotation("org.openjdk.jmh.annotations.State") @@ -56,7 +56,7 @@ dependencies { implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") implementation("org.jetbrains.kotlinx:kotlinx-io:0.2.0-npm-dev-11") - implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20") + implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.0") implementation("org.slf4j:slf4j-simple:1.7.30") // plotting diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index ad2a57597..a9c192e55 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -5,11 +5,7 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import space.kscience.kmath.asm.compileToExpression -import space.kscience.kmath.ast.MstField -import space.kscience.kmath.ast.toExpression -import space.kscience.kmath.expressions.Expression -import space.kscience.kmath.expressions.expressionInField -import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.expressions.* import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt index a4b8b7ca4..c6308c567 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.ast +import space.kscience.kmath.expressions.MstField +import space.kscience.kmath.expressions.interpret import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt index 5cf96adaa..41c3c64d7 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt @@ -3,12 +3,12 @@ package space.kscience.kmath.stat import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking +import org.apache.commons.rng.sampling.distribution.BoxMullerNormalizedGaussianSampler import org.apache.commons.rng.simple.RandomSource import space.kscience.kmath.samplers.GaussianSampler import java.time.Duration import java.time.Instant import org.apache.commons.rng.sampling.distribution.GaussianSampler as CMGaussianSampler -import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler as CMZigguratNormalizedGaussianSampler private suspend fun runKMathChained(): Duration { val generator = RandomGenerator.fromSource(RandomSource.MT, 123L) @@ -34,7 +34,7 @@ private fun runApacheDirect(): Duration { val rng = RandomSource.create(RandomSource.MT, 123L) val sampler = CMGaussianSampler.of( - CMZigguratNormalizedGaussianSampler.of(rng), + BoxMullerNormalizedGaussianSampler.of(rng), 7.0, 2.0 ) @@ -59,8 +59,8 @@ private fun runApacheDirect(): Duration { * Comparing chain sampling performance with direct sampling performance */ fun main(): Unit = runBlocking(Dispatchers.Default) { - val chainJob = async { runKMathChained() } val directJob = async { runApacheDirect() } + val chainJob = async { runKMathChained() } println("KMath Chained: ${chainJob.await()}") println("Apache Direct: ${directJob.await()}") } diff --git a/gradle.properties b/gradle.properties index 50123b16c..725d380f7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,5 +4,5 @@ kotlin.mpp.stability.nowarn=true kotlin.native.enableDependencyPropagation=false kotlin.parallel.tasks.in.project=true org.gradle.configureondemand=true -org.gradle.jvmargs=-XX:MaxMetaspaceSize=9G +org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G org.gradle.parallel=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 442d9132e..f371643ee 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 44faa5cd5..547775efc 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -3,9 +3,9 @@ Abstract syntax tree expression representation and related optimizations. - [expression-language](src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser - - [mst](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation - - [mst-building](src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure - - [mst-interpreter](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter + - [mst](../kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation + - [mst-building](../kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt) : MST building algebraic structure + - [mst-interpreter](../kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt) : MST interpreter - [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler - [mst-js-codegen](src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index e3a7faf0a..28abc06f2 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -1,7 +1,6 @@ -import ru.mipt.npm.gradle.Maturity - plugins { - id("ru.mipt.npm.gradle.mpp") + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common") } kotlin.js { @@ -52,7 +51,7 @@ tasks.dokkaHtml { } readme { - maturity = Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index 14e14404c..b056496a8 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.ast.MST +import space.kscience.kmath.expressions.MST /** * Renders [MST] to [MathSyntax]. diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index 95108ba45..8cbc4e614 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.ast.MST import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature +import space.kscience.kmath.expressions.MST import space.kscience.kmath.operations.* import kotlin.reflect.KClass diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt index 1b8ec1490..be7a5df9d 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt @@ -1,8 +1,8 @@ package space.kscisnce.kmath.ast -import space.kscience.kmath.ast.MstField -import space.kscience.kmath.ast.toExpression +import space.kscience.kmath.expressions.MstField import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.expressions.toExpression import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt index 796ffce1e..1d04a72db 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt @@ -1,10 +1,10 @@ package space.kscience.kmath.estree -import space.kscience.kmath.ast.MST -import space.kscience.kmath.ast.MST.* import space.kscience.kmath.estree.internal.ESTreeBuilder import space.kscience.kmath.estree.internal.estree.BaseExpression import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.MST.* import space.kscience.kmath.expressions.invoke import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra @@ -26,16 +26,17 @@ internal fun MST.compileWith(algebra: Algebra): Expression { is Unary -> when { algebra is NumericAlgebra && node.value is Numeric -> constant( - algebra.unaryOperationFunction(node.operation)(algebra.number(node.value.value))) + algebra.unaryOperationFunction(node.operation)(algebra.number((node.value as Numeric).value))) else -> call(algebra.unaryOperationFunction(node.operation), visit(node.value)) } is Binary -> when { algebra is NumericAlgebra && node.left is Numeric && node.right is Numeric -> constant( - algebra - .binaryOperationFunction(node.operation) - .invoke(algebra.number(node.left.value), algebra.number(node.right.value)) + algebra.binaryOperationFunction(node.operation).invoke( + algebra.number((node.left as Numeric).value), + algebra.number((node.right as Numeric).value) + ) ) algebra is NumericAlgebra && node.left is Numeric -> call( @@ -70,12 +71,12 @@ public fun MST.compileToExpression(algebra: Algebra): Expression /** * Compile given MST to expression and evaluate it against [arguments] */ -public inline fun MST.compile(algebra: Algebra, arguments: Map): T = +public inline fun MST.compile(algebra: Algebra, arguments: Map): T = compileToExpression(algebra).invoke(arguments) /** * Compile given MST to expression and evaluate it against [arguments] */ -public inline fun MST.compile(algebra: Algebra, vararg arguments: Pair): T = +public inline fun MST.compile(algebra: Algebra, vararg arguments: Pair): T = compileToExpression(algebra).invoke(*arguments) diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt index fb8d73c0c..4944e2fc3 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.estree -import space.kscience.kmath.ast.* import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.toComplex +import space.kscience.kmath.expressions.* import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.DoubleField diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt index 24c003e3e..0217ffcec 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.estree -import space.kscience.kmath.ast.MstExtendedField +import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt index c83fbc391..939c82270 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.estree -import space.kscience.kmath.ast.MstExtendedField +import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt index 0b1c1c33e..49fa31b9f 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.estree -import space.kscience.kmath.ast.MstRing +import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.invoke diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt index ee2b6fb54..a8716a64e 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt @@ -2,9 +2,9 @@ package space.kscience.kmath.asm import space.kscience.kmath.asm.internal.AsmBuilder import space.kscience.kmath.asm.internal.buildName -import space.kscience.kmath.ast.MST -import space.kscience.kmath.ast.MST.* import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.MST.* import space.kscience.kmath.expressions.invoke import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra @@ -34,15 +34,17 @@ internal fun MST.compileWith(type: Class, algebra: Algebra): Exp is Unary -> when { algebra is NumericAlgebra && node.value is Numeric -> loadObjectConstant( - algebra.unaryOperationFunction(node.operation)(algebra.number(node.value.value))) + algebra.unaryOperationFunction(node.operation)(algebra.number((node.value as Numeric).value))) else -> buildCall(algebra.unaryOperationFunction(node.operation)) { visit(node.value) } } is Binary -> when { algebra is NumericAlgebra && node.left is Numeric && node.right is Numeric -> loadObjectConstant( - algebra.binaryOperationFunction(node.operation) - .invoke(algebra.number(node.left.value), algebra.number(node.right.value)) + algebra.binaryOperationFunction(node.operation).invoke( + algebra.number((node.left as Numeric).value), + algebra.number((node.right as Numeric).value) + ) ) algebra is NumericAlgebra && node.left is Numeric -> buildCall( @@ -71,18 +73,18 @@ internal fun MST.compileWith(type: Class, algebra: Algebra): Exp /** * Create a compiled expression with given [MST] and given [algebra]. */ -public inline fun MST.compileToExpression(algebra: Algebra): Expression = +public inline fun MST.compileToExpression(algebra: Algebra): Expression = compileWith(T::class.java, algebra) /** * Compile given MST to expression and evaluate it against [arguments] */ -public inline fun MST.compile(algebra: Algebra, arguments: Map): T = +public inline fun MST.compile(algebra: Algebra, arguments: Map): T = compileToExpression(algebra).invoke(arguments) /** * Compile given MST to expression and evaluate it against [arguments] */ -public inline fun MST.compile(algebra: Algebra, vararg arguments: Pair): T = +public inline fun MST.compile(algebra: Algebra, vararg arguments: Pair): T = compileToExpression(algebra).invoke(*arguments) diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt index a03af5bf9..43704c815 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt @@ -5,8 +5,8 @@ import org.objectweb.asm.Opcodes.* import org.objectweb.asm.Type.* import org.objectweb.asm.commons.InstructionAdapter import space.kscience.kmath.asm.internal.AsmBuilder.ClassLoader -import space.kscience.kmath.ast.MST import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST import java.lang.invoke.MethodHandles import java.lang.invoke.MethodType import java.util.stream.Collectors.toMap diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt index 4522c966f..646879c02 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt @@ -2,8 +2,8 @@ package space.kscience.kmath.asm.internal import org.objectweb.asm.* import org.objectweb.asm.commons.InstructionAdapter -import space.kscience.kmath.ast.MST import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt index 8ecb0adda..2991dd68a 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt @@ -13,6 +13,7 @@ import com.github.h0tk3y.betterParse.lexer.literalToken import com.github.h0tk3y.betterParse.lexer.regexToken import com.github.h0tk3y.betterParse.parser.ParseResult import com.github.h0tk3y.betterParse.parser.Parser +import space.kscience.kmath.expressions.MST import space.kscience.kmath.operations.FieldOperations import space.kscience.kmath.operations.GroupOperations import space.kscience.kmath.operations.PowerOperations diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt index 096bf4447..aefe15fe9 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.asm -import space.kscience.kmath.ast.* import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.toComplex +import space.kscience.kmath.expressions.* import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.DoubleField diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt index d1a216ede..4ab953b26 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.asm -import space.kscience.kmath.ast.MstExtendedField -import space.kscience.kmath.ast.MstField -import space.kscience.kmath.ast.MstGroup +import space.kscience.kmath.expressions.MstExtendedField +import space.kscience.kmath.expressions.MstField +import space.kscience.kmath.expressions.MstGroup import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt index 75a3ffaee..6c988cbe2 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.asm -import space.kscience.kmath.ast.MstExtendedField +import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt index 144d63eea..14868ee01 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.asm -import space.kscience.kmath.ast.MstRing +import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.invoke diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt index 1450cab84..e4eef757d 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.ast +import space.kscience.kmath.expressions.evaluate import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Field import kotlin.test.Test diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt index 2b83e566e..584737633 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt @@ -2,6 +2,9 @@ package space.kscience.kmath.ast import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.ComplexField +import space.kscience.kmath.expressions.MstField +import space.kscience.kmath.expressions.evaluate +import space.kscience.kmath.expressions.interpret import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt index 5850ea23d..9d335dbf9 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.ast.MST.Numeric import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import space.kscience.kmath.expressions.MST.Numeric import kotlin.test.Test internal class TestFeatures { diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt index 599bee436..8902a63e3 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.ast.MST import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import space.kscience.kmath.expressions.MST import space.kscience.kmath.operations.GroupOperations import kotlin.test.Test diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt index 6fadef6cd..c1c4468aa 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.ast.MST import space.kscience.kmath.ast.rendering.TestUtils.testMathML +import space.kscience.kmath.expressions.MST import space.kscience.kmath.operations.GroupOperations import kotlin.test.Test diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt index e6359bcc9..5a0d4f8e4 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt @@ -1,7 +1,7 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.ast.MST import space.kscience.kmath.ast.parseMath +import space.kscience.kmath.expressions.MST import kotlin.test.assertEquals internal object TestUtils { diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index 56dcef29a..2f9a83df2 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -1,5 +1,6 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + kotlin("jvm") + id("ru.mipt.npm.gradle.common") } description = "Commons math binding for kmath" diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index 5b9dc3ba0..5244a03f0 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -1,7 +1,6 @@ -import ru.mipt.npm.gradle.Maturity - plugins { - id("ru.mipt.npm.gradle.mpp") + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common") id("ru.mipt.npm.gradle.native") } @@ -19,7 +18,7 @@ kotlin.sourceSets { readme { description = "Complex numbers and quaternions." - maturity = Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index f76372a3d..08aa1bbe4 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -217,6 +217,332 @@ public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/k public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } +public abstract class space/kscience/kmath/expressions/MST { +} + +public final class space/kscience/kmath/expressions/MST$Binary : space/kscience/kmath/expressions/MST { + public fun (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Lspace/kscience/kmath/expressions/MST; + public final fun component3 ()Lspace/kscience/kmath/expressions/MST; + public final fun copy (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public static synthetic fun copy$default (Lspace/kscience/kmath/expressions/MST$Binary;Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;ILjava/lang/Object;)Lspace/kscience/kmath/expressions/MST$Binary; + public fun equals (Ljava/lang/Object;)Z + public final fun getLeft ()Lspace/kscience/kmath/expressions/MST; + public final fun getOperation ()Ljava/lang/String; + public final fun getRight ()Lspace/kscience/kmath/expressions/MST; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class space/kscience/kmath/expressions/MST$Numeric : space/kscience/kmath/expressions/MST { + public fun (Ljava/lang/Number;)V + public final fun component1 ()Ljava/lang/Number; + public final fun copy (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; + public static synthetic fun copy$default (Lspace/kscience/kmath/expressions/MST$Numeric;Ljava/lang/Number;ILjava/lang/Object;)Lspace/kscience/kmath/expressions/MST$Numeric; + public fun equals (Ljava/lang/Object;)Z + public final fun getValue ()Ljava/lang/Number; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class space/kscience/kmath/expressions/MST$Symbolic : space/kscience/kmath/expressions/MST { + public fun (Ljava/lang/String;)V + public final fun component1 ()Ljava/lang/String; + public final fun copy (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; + public static synthetic fun copy$default (Lspace/kscience/kmath/expressions/MST$Symbolic;Ljava/lang/String;ILjava/lang/Object;)Lspace/kscience/kmath/expressions/MST$Symbolic; + public fun equals (Ljava/lang/Object;)Z + public final fun getValue ()Ljava/lang/String; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class space/kscience/kmath/expressions/MST$Unary : space/kscience/kmath/expressions/MST { + public fun (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Lspace/kscience/kmath/expressions/MST; + public final fun copy (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public static synthetic fun copy$default (Lspace/kscience/kmath/expressions/MST$Unary;Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;ILjava/lang/Object;)Lspace/kscience/kmath/expressions/MST$Unary; + public fun equals (Ljava/lang/Object;)Z + public final fun getOperation ()Ljava/lang/String; + public final fun getValue ()Lspace/kscience/kmath/expressions/MST; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class space/kscience/kmath/expressions/MSTKt { + public static final fun evaluate (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/expressions/MST;)Ljava/lang/Object; + public static final fun interpret (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/operations/Algebra;Ljava/util/Map;)Ljava/lang/Object; + public static final fun interpret (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/operations/Algebra;[Lkotlin/Pair;)Ljava/lang/Object; + public static final fun toExpression (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/operations/Algebra;)Lspace/kscience/kmath/expressions/Expression; +} + +public final class space/kscience/kmath/expressions/MstAlgebra : space/kscience/kmath/operations/NumericAlgebra { + public static final field INSTANCE Lspace/kscience/kmath/expressions/MstAlgebra; + public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; + public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; + public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; +} + +public final class space/kscience/kmath/expressions/MstExtendedField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumericAlgebra { + public static final field INSTANCE Lspace/kscience/kmath/expressions/MstExtendedField; + public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; + public fun acos (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun acosh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; + public fun asin (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun asinh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; + public fun atan (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun atanh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; + public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; + public fun cos (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun cosh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun div (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun div (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun divide (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; + public fun exp (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun getOne ()Ljava/lang/Object; + public fun getOne ()Lspace/kscience/kmath/expressions/MST$Numeric; + public synthetic fun getZero ()Ljava/lang/Object; + public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric; + public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; + public fun ln (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun minus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun multiply (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; + public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun pow (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun power (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/expressions/MST;D)Lspace/kscience/kmath/expressions/MST; + public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; + public fun sin (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun sinh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; + public fun sqrt (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; + public fun tan (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun tanh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun times (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryMinus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; +} + +public final class space/kscience/kmath/expressions/MstField : space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { + public static final field INSTANCE Lspace/kscience/kmath/expressions/MstField; + public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun div (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun div (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun divide (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun getOne ()Ljava/lang/Object; + public fun getOne ()Lspace/kscience/kmath/expressions/MST$Numeric; + public synthetic fun getZero ()Ljava/lang/Object; + public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric; + public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun minus (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun minus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun multiply (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; + public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun plus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/expressions/MST;D)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun times (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryMinus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; +} + +public final class space/kscience/kmath/expressions/MstGroup : space/kscience/kmath/operations/Group, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/ScaleOperations { + public static final field INSTANCE Lspace/kscience/kmath/expressions/MstGroup; + public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun div (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun getZero ()Ljava/lang/Object; + public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric; + public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun minus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; + public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/expressions/MST;D)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun times (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryMinus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; +} + +public final class space/kscience/kmath/expressions/MstRing : space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/Ring, space/kscience/kmath/operations/ScaleOperations { + public static final field INSTANCE Lspace/kscience/kmath/expressions/MstRing; + public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; + public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun div (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun getOne ()Ljava/lang/Object; + public fun getOne ()Lspace/kscience/kmath/expressions/MST$Numeric; + public synthetic fun getZero ()Ljava/lang/Object; + public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric; + public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun minus (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun minus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun multiply (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; + public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun plus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/expressions/MST;D)Lspace/kscience/kmath/expressions/MST$Binary; + public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; + public fun times (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryMinus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; +} + public final class space/kscience/kmath/expressions/SimpleAutoDiffExpression : space/kscience/kmath/expressions/FirstDerivativeExpression { public fun (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)V public fun derivativeOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression; diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 2fed3eb2f..92a5f419d 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,7 +1,6 @@ -import ru.mipt.npm.gradle.Maturity - plugins { - id("ru.mipt.npm.gradle.mpp") + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common") id("ru.mipt.npm.gradle.native") } @@ -15,7 +14,7 @@ kotlin.sourceSets { readme { description = "Core classes, algebra definitions, basic linear algebra" - maturity = Maturity.DEVELOPMENT + maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt similarity index 98% rename from kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt index 538db0caa..d05e3a389 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt @@ -1,6 +1,5 @@ -package space.kscience.kmath.ast +package space.kscience.kmath.expressions -import space.kscience.kmath.expressions.Expression import space.kscience.kmath.misc.StringSymbol import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt similarity index 99% rename from kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt index 33fca7521..3151ebaa0 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt @@ -1,4 +1,4 @@ -package space.kscience.kmath.ast +package space.kscience.kmath.expressions import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index b68dd2e8d..d3f6711a6 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -1,4 +1,6 @@ -plugins { id("ru.mipt.npm.gradle.mpp") } +plugins { + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common")} kotlin.sourceSets { all { diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index 3c73f34e6..885f3c227 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -1,5 +1,6 @@ plugins { - id("ru.mipt.npm.gradle.mpp") + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common") id("ru.mipt.npm.gradle.native") } diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index 5091139ac..d3a49aeb0 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -1,7 +1,6 @@ -import ru.mipt.npm.gradle.Maturity - plugins { - id("ru.mipt.npm.gradle.jvm") + kotlin("jvm") + id("ru.mipt.npm.gradle.common") } dependencies { @@ -10,7 +9,7 @@ dependencies { } readme { - maturity = Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index 0dcaf330a..f6d12decd 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -1,5 +1,6 @@ plugins { - id("ru.mipt.npm.gradle.mpp") + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common") } kotlin.sourceSets.commonMain { diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 51fc75501..a690170db 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -1,5 +1,6 @@ plugins { - id("ru.mipt.npm.gradle.mpp") + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common") } kotlin.sourceSets.commonMain { diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index ca4bbf6b8..637761497 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.integration import space.kscience.kmath.misc.UnstableKMathAPI +import kotlin.jvm.JvmInline import kotlin.reflect.KClass public class UnivariateIntegrand internal constructor( @@ -26,7 +27,8 @@ public fun UnivariateIntegrand( public typealias UnivariateIntegrator = Integrator> -public inline class IntegrationRange>(public val range: ClosedRange) : IntegrandFeature +@JvmInline +public value class IntegrationRange>(public val range: ClosedRange) : IntegrandFeature public val UnivariateIntegrand.value: T? get() = getFeature>()?.value diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LoessInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LoessInterpolator.kt deleted file mode 100644 index 26e7a4072..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LoessInterpolator.kt +++ /dev/null @@ -1,296 +0,0 @@ -package space.kscience.kmath.interpolation -// -//import space.kscience.kmath.functions.PiecewisePolynomial -//import space.kscience.kmath.operations.Ring -//import space.kscience.kmath.structures.Buffer -//import kotlin.math.abs -//import kotlin.math.sqrt -// -// -///** -// * Original code: https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/LoessInterpolator.java -// */ -//class LoessInterpolator>(override val algebra: Ring) : PolynomialInterpolator { -// /** -// * The bandwidth parameter: when computing the loess fit at -// * a particular point, this fraction of source points closest -// * to the current point is taken into account for computing -// * a least-squares regression. -// * -// * -// * A sensible value is usually 0.25 to 0.5. -// */ -// private var bandwidth = 0.0 -// -// /** -// * The number of robustness iterations parameter: this many -// * robustness iterations are done. -// * -// * -// * A sensible value is usually 0 (just the initial fit without any -// * robustness iterations) to 4. -// */ -// private var robustnessIters = 0 -// -// /** -// * If the median residual at a certain robustness iteration -// * is less than this amount, no more iterations are done. -// */ -// private var accuracy = 0.0 -// -// /** -// * Constructs a new [LoessInterpolator] -// * with a bandwidth of [.DEFAULT_BANDWIDTH], -// * [.DEFAULT_ROBUSTNESS_ITERS] robustness iterations -// * and an accuracy of {#link #DEFAULT_ACCURACY}. -// * See [.LoessInterpolator] for an explanation of -// * the parameters. -// */ -// fun LoessInterpolator() { -// bandwidth = DEFAULT_BANDWIDTH -// robustnessIters = DEFAULT_ROBUSTNESS_ITERS -// accuracy = DEFAULT_ACCURACY -// } -// -// fun LoessInterpolator(bandwidth: Double, robustnessIters: Int) { -// this(bandwidth, robustnessIters, DEFAULT_ACCURACY) -// } -// -// fun LoessInterpolator(bandwidth: Double, robustnessIters: Int, accuracy: Double) { -// if (bandwidth < 0 || -// bandwidth > 1 -// ) { -// throw OutOfRangeException(LocalizedFormats.BANDWIDTH, bandwidth, 0, 1) -// } -// this.bandwidth = bandwidth -// if (robustnessIters < 0) { -// throw NotPositiveException(LocalizedFormats.ROBUSTNESS_ITERATIONS, robustnessIters) -// } -// this.robustnessIters = robustnessIters -// this.accuracy = accuracy -// } -// -// fun interpolate( -// xval: DoubleArray, -// yval: DoubleArray -// ): PolynomialSplineFunction { -// return SplineInterpolator().interpolate(xval, smooth(xval, yval)) -// } -// -// fun XYZPointSet.smooth(): XYPointSet { -// checkAllFiniteReal(x) -// checkAllFiniteReal(y) -// checkAllFiniteReal(z) -// MathArrays.checkOrder(xval) -// if (size == 1) { -// return doubleArrayOf(y[0]) -// } -// if (size == 2) { -// return doubleArrayOf(y[0], y[1]) -// } -// val bandwidthInPoints = (bandwidth * size).toInt() -// if (bandwidthInPoints < 2) { -// throw NumberIsTooSmallException( -// LocalizedFormats.BANDWIDTH, -// bandwidthInPoints, 2, true -// ) -// } -// val res = DoubleArray(size) -// val residuals = DoubleArray(size) -// val sortedResiduals = DoubleArray(size) -// val robustnessWeights = DoubleArray(size) -// // Do an initial fit and 'robustnessIters' robustness iterations. -// // This is equivalent to doing 'robustnessIters+1' robustness iterations -// // starting with all robustness weights set to 1. -// Arrays.fill(robustnessWeights, 1.0) -// for (iter in 0..robustnessIters) { -// val bandwidthInterval = intArrayOf(0, bandwidthInPoints - 1) -// // At each x, compute a local weighted linear regression -// for (i in 0 until size) { -//// val x = x[i] -// // Find out the interval of source points on which -// // a regression is to be made. -// if (i > 0) { -// updateBandwidthInterval(x, z, i, bandwidthInterval) -// } -// val ileft = bandwidthInterval[0] -// val iright = bandwidthInterval[1] -// // Compute the point of the bandwidth interval that is -// // farthest from x -// val edge: Int -// edge = if (x[i] - x[ileft] > x[iright] - x[i]) { -// ileft -// } else { -// iright -// } -// // Compute a least-squares linear fit weighted by -// // the product of robustness weights and the tricube -// // weight function. -// // See http://en.wikipedia.org/wiki/Linear_regression -// // (section "Univariate linear case") -// // and http://en.wikipedia.org/wiki/Weighted_least_squares -// // (section "Weighted least squares") -// var sumWeights = 0.0 -// var sumX = 0.0 -// var sumXSquared = 0.0 -// var sumY = 0.0 -// var sumXY = 0.0 -// val denom: Double = abs(1.0 / (x[edge] - x[i])) -// for (k in ileft..iright) { -// val xk = x[k] -// val yk = y[k] -// val dist = if (k < i) x - xk else xk - x[i] -// val w = tricube(dist * denom) * robustnessWeights[k] * z[k] -// val xkw = xk * w -// sumWeights += w -// sumX += xkw -// sumXSquared += xk * xkw -// sumY += yk * w -// sumXY += yk * xkw -// } -// val meanX = sumX / sumWeights -// val meanY = sumY / sumWeights -// val meanXY = sumXY / sumWeights -// val meanXSquared = sumXSquared / sumWeights -// val beta: Double -// beta = if (sqrt(abs(meanXSquared - meanX * meanX)) < accuracy) { -// 0.0 -// } else { -// (meanXY - meanX * meanY) / (meanXSquared - meanX * meanX) -// } -// val alpha = meanY - beta * meanX -// res[i] = beta * x[i] + alpha -// residuals[i] = abs(y[i] - res[i]) -// } -// // No need to recompute the robustness weights at the last -// // iteration, they won't be needed anymore -// if (iter == robustnessIters) { -// break -// } -// // Recompute the robustness weights. -// // Find the median residual. -// // An arraycopy and a sort are completely tractable here, -// // because the preceding loop is a lot more expensive -// java.lang.System.arraycopy(residuals, 0, sortedResiduals, 0, size) -// Arrays.sort(sortedResiduals) -// val medianResidual = sortedResiduals[size / 2] -// if (abs(medianResidual) < accuracy) { -// break -// } -// for (i in 0 until size) { -// val arg = residuals[i] / (6 * medianResidual) -// if (arg >= 1) { -// robustnessWeights[i] = 0.0 -// } else { -// val w = 1 - arg * arg -// robustnessWeights[i] = w * w -// } -// } -// } -// return res -// } -// -// fun smooth(xval: DoubleArray, yval: DoubleArray): DoubleArray { -// if (xval.size != yval.size) { -// throw DimensionMismatchException(xval.size, yval.size) -// } -// val unitWeights = DoubleArray(xval.size) -// Arrays.fill(unitWeights, 1.0) -// return smooth(xval, yval, unitWeights) -// } -// -// /** -// * Given an index interval into xval that embraces a certain number of -// * points closest to `xval[i-1]`, update the interval so that it -// * embraces the same number of points closest to `xval[i]`, -// * ignoring zero weights. -// * -// * @param xval Arguments array. -// * @param weights Weights array. -// * @param i Index around which the new interval should be computed. -// * @param bandwidthInterval a two-element array {left, right} such that: -// * `(left==0 or xval[i] - xval[left-1] > xval[right] - xval[i])` -// * and -// * `(right==xval.length-1 or xval[right+1] - xval[i] > xval[i] - xval[left])`. -// * The array will be updated. -// */ -// private fun updateBandwidthInterval( -// xval: Buffer, weights: Buffer, -// i: Int, -// bandwidthInterval: IntArray -// ) { -// val left = bandwidthInterval[0] -// val right = bandwidthInterval[1] -// // The right edge should be adjusted if the next point to the right -// // is closer to xval[i] than the leftmost point of the current interval -// val nextRight = nextNonzero(weights, right) -// if (nextRight < xval.size && xval[nextRight] - xval[i] < xval[i] - xval[left]) { -// val nextLeft = nextNonzero(weights, bandwidthInterval[0]) -// bandwidthInterval[0] = nextLeft -// bandwidthInterval[1] = nextRight -// } -// } -// -// /** -// * Return the smallest index `j` such that -// * `j > i && (j == weights.length || weights[j] != 0)`. -// * -// * @param weights Weights array. -// * @param i Index from which to start search. -// * @return the smallest compliant index. -// */ -// private fun nextNonzero(weights: Buffer, i: Int): Int { -// var j = i + 1 -// while (j < weights.size && weights[j] == 0.0) { -// ++j -// } -// return j -// } -// -// /** -// * Compute the -// * [tricube](http://en.wikipedia.org/wiki/Local_regression#Weight_function) -// * weight function -// * -// * @param x Argument. -// * @return `(1 - |x|3)3` for |x| < 1, 0 otherwise. -// */ -// private fun tricube(x: Double): Double { -// val absX: Double = FastMath.abs(x) -// if (absX >= 1.0) { -// return 0.0 -// } -// val tmp = 1 - absX * absX * absX -// return tmp * tmp * tmp -// } -// -// /** -// * Check that all elements of an array are finite real numbers. -// * -// * @param values Values array. -// * @throws org.apache.commons.math4.exception.NotFiniteNumberException -// * if one of the values is not a finite real number. -// */ -// private fun checkAllFiniteReal(values: DoubleArray) { -// for (i in values.indices) { -// MathUtils.checkFinite(values[i]) -// } -// } -// -// override fun interpolatePolynomials(points: Collection>): PiecewisePolynomial { -// TODO("not implemented") //To change body of created functions use File | Settings | File Templates. -// } -// -// companion object { -// /** Default value of the bandwidth parameter. */ -// const val DEFAULT_BANDWIDTH = 0.3 -// -// /** Default value of the number of robustness iterations. */ -// const val DEFAULT_ROBUSTNESS_ITERS = 2 -// -// /** -// * Default value for accuracy. -// */ -// const val DEFAULT_ACCURACY = 1e-12 -// } -//} \ No newline at end of file diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index 9d1b2d4d6..90068a4bf 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -1,4 +1,6 @@ -plugins { id("ru.mipt.npm.gradle.mpp") } +plugins { + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common")} kotlin.sourceSets.commonMain { dependencies { diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index 1337e40aa..980c46d13 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -1,5 +1,6 @@ plugins { - id("ru.mipt.npm.gradle.mpp") + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common") } kscience { diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index a7c0c7e01..dfc0904e0 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -1,5 +1,6 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + kotlin("jvm") + id("ru.mipt.npm.gradle.common") } dependencies { diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt index ab3547cda..fe73a63d6 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -1,10 +1,10 @@ package space.kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.api.SFun -import space.kscience.kmath.ast.MST -import space.kscience.kmath.ast.MstAlgebra -import space.kscience.kmath.ast.interpret import space.kscience.kmath.expressions.DifferentiableExpression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.MstAlgebra +import space.kscience.kmath.expressions.interpret import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.NumericAlgebra diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt index 82b801f91..a3ab5cec5 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -1,10 +1,10 @@ package space.kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.api.* -import space.kscience.kmath.ast.MST -import space.kscience.kmath.ast.MstAlgebra -import space.kscience.kmath.ast.MstExtendedField -import space.kscience.kmath.ast.MstExtendedField.unaryMinus +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.MstAlgebra +import space.kscience.kmath.expressions.MstExtendedField +import space.kscience.kmath.expressions.MstExtendedField.unaryMinus import space.kscience.kmath.operations.* /** diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index c4c25d789..1f3a0185f 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -2,8 +2,8 @@ package space.kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.api.* import space.kscience.kmath.asm.compileToExpression -import space.kscience.kmath.ast.MstAlgebra import space.kscience.kmath.ast.parseMath +import space.kscience.kmath.expressions.MstAlgebra import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.DoubleField import kotlin.test.Test diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 1ccd1bed8..d6107dfd0 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -1,11 +1,12 @@ plugins { - id("ru.mipt.npm.gradle.mpp") + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common") id("ru.mipt.npm.gradle.native") } readme { + maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT description = """ An API and basic implementation for arranging objects in a continous memory block. """.trimIndent() - maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT } \ No newline at end of file diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 2954a1e65..6c4f5ad74 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -1,7 +1,6 @@ -import ru.mipt.npm.gradle.Maturity - plugins { - id("ru.mipt.npm.gradle.jvm") + kotlin("jvm") + id("ru.mipt.npm.gradle.common") } dependencies { @@ -14,7 +13,7 @@ dependencies { readme { description = "ND4J NDStructure implementation and according NDAlgebra classes" - maturity = Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index c2ebb7ea1..e8f629f7a 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -1,8 +1,9 @@ plugins { - id("ru.mipt.npm.gradle.mpp") + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common") } -kscience{ +kscience { useAtomic() } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt new file mode 100644 index 000000000..e13d5ff69 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt @@ -0,0 +1,45 @@ +package space.kscience.kmath.stat + +import space.kscience.kmath.operations.* +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.indices + +/** + * Arithmetic mean + */ +public class Mean( + private val group: Group, + private val division: (sum: T, count: Int) -> T, +) : ComposableStatistic, T>, BlockingStatistic { + + override fun evaluateBlocking(data: Buffer): T = group { + var res = zero + for (i in data.indices) { + res += data[i] + } + division(res, data.size) + } + + override suspend fun evaluate(data: Buffer): T = super.evaluate(data) + + public override suspend fun computeIntermediate(data: Buffer): Pair = + evaluateBlocking(data) to data.size + + public override suspend fun composeIntermediate(first: Pair, second: Pair): Pair = + group { first.first + second.first } to (first.second + second.second) + + public override suspend fun toResult(intermediate: Pair): T = group { + division(intermediate.first, intermediate.second) + } + + public companion object { + //TODO replace with optimized version which respects overflow + public val double: Mean = Mean(DoubleField) { sum, count -> sum / count } + public val int: Mean = Mean(IntRing) { sum, count -> sum / count } + public val long: Mean = Mean(LongRing) { sum, count -> sum / count } + + public fun evaluate(buffer: Buffer): Double = double.evaluateBlocking(buffer) + public fun evaluate(buffer: Buffer): Int = int.evaluateBlocking(buffer) + public fun evaluate(buffer: Buffer): Long = long.evaluateBlocking(buffer) + } +} \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Median.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Median.kt new file mode 100644 index 000000000..a34e5e9a9 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Median.kt @@ -0,0 +1,16 @@ +package space.kscience.kmath.stat + +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asSequence + +/** + * Non-composable median + */ +public class Median(private val comparator: Comparator) : BlockingStatistic { + public override fun evaluateBlocking(data: Buffer): T = + data.asSequence().sortedWith(comparator).toList()[data.size / 2] //TODO check if this is correct + + public companion object { + public val real: Median = Median { a: Double, b: Double -> a.compareTo(b) } + } +} \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt index 67f55aea6..5e6da8f5a 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt @@ -8,16 +8,19 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.runningReduce import space.kscience.kmath.coroutines.mapParallel -import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.asIterable -import space.kscience.kmath.structures.asSequence /** * A function, that transforms a buffer of random quantities to some resulting value */ public interface Statistic { - public suspend operator fun invoke(data: Buffer): R + public suspend fun evaluate(data: Buffer): R +} + +public interface BlockingStatistic: Statistic{ + public fun evaluateBlocking(data: Buffer): R + + override suspend fun evaluate(data: Buffer): R = evaluateBlocking(data) } /** @@ -36,7 +39,7 @@ public interface ComposableStatistic : Statistic { //Transform block to result public suspend fun toResult(intermediate: I): R - public override suspend fun invoke(data: Buffer): R = toResult(computeIntermediate(data)) + public override suspend fun evaluate(data: Buffer): R = toResult(computeIntermediate(data)) } @FlowPreview @@ -55,46 +58,9 @@ private fun ComposableStatistic.flowIntermediate( * * The resulting flow contains values that include the whole previous statistics, not only the last chunk. */ -@FlowPreview -@ExperimentalCoroutinesApi +@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class) public fun ComposableStatistic.flow( flow: Flow>, dispatcher: CoroutineDispatcher = Dispatchers.Default, ): Flow = flowIntermediate(flow, dispatcher).map(::toResult) -/** - * Arithmetic mean - */ -public class Mean( - private val group: Group, - private val division: (sum: T, count: Int) -> T, -) : ComposableStatistic, T> { - public override suspend fun computeIntermediate(data: Buffer): Pair = - group { sum(data.asIterable()) } to data.size - - public override suspend fun composeIntermediate(first: Pair, second: Pair): Pair = - group { first.first + second.first } to (first.second + second.second) - - public override suspend fun toResult(intermediate: Pair): T = group { - division(intermediate.first, intermediate.second) - } - - public companion object { - //TODO replace with optimized version which respects overflow - public val double: Mean = Mean(DoubleField) { sum, count -> sum / count } - public val int: Mean = Mean(IntRing) { sum, count -> sum / count } - public val long: Mean = Mean(LongRing) { sum, count -> sum / count } - } -} - -/** - * Non-composable median - */ -public class Median(private val comparator: Comparator) : Statistic { - public override suspend fun invoke(data: Buffer): T = - data.asSequence().sortedWith(comparator).toList()[data.size / 2] //TODO check if this is correct - - public companion object { - public val real: Median = Median { a: Double, b: Double -> a.compareTo(b) } - } -} diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt index e175c76ee..868208180 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -1,17 +1,18 @@ package space.kscience.kmath.stat -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import space.kscience.kmath.samplers.GaussianSampler internal class CommonsDistributionsTest { @Test - fun testNormalDistributionSuspend() = runBlocking { + fun testNormalDistributionSuspend() = GlobalScope.launch { val distribution = GaussianSampler(7.0, 2.0) val generator = RandomGenerator.default(1) val sample = distribution.sample(generator).nextBuffer(1000) - Assertions.assertEquals(7.0, Mean.double(sample), 0.2) + Assertions.assertEquals(7.0, Mean.evaluate(sample), 0.2) } @Test @@ -19,8 +20,6 @@ internal class CommonsDistributionsTest { val distribution = GaussianSampler(7.0, 2.0) val generator = RandomGenerator.default(1) val sample = distribution.sample(generator).nextBufferBlocking(1000) - runBlocking { - Assertions.assertEquals(7.0, Mean.double(sample), 0.2) - } + Assertions.assertEquals(7.0, Mean.evaluate(sample), 0.2) } } diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt index 908c5775b..e1891fb68 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt @@ -17,14 +17,12 @@ internal class StatisticTest { val chunked = data.chunked(1000) @Test - fun testParallelMean() { - runBlocking { - val average = Mean.double - .flow(chunked) //create a flow with results - .drop(99) // Skip first 99 values and use one with total data - .first() //get 1e5 data samples average + fun testParallelMean() = runBlocking { + val average = Mean.double + .flow(chunked) //create a flow with results + .drop(99) // Skip first 99 values and use one with total data + .first() //get 1e5 data samples average - println(average) - } + println(average) } } diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 94744f528..232bd1388 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -1,5 +1,6 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + kotlin("jvm") + id("ru.mipt.npm.gradle.common") } description = "Binding for https://github.com/JetBrains-Research/viktor" diff --git a/settings.gradle.kts b/settings.gradle.kts index 38a4d86ff..ef9000fbb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,18 +7,17 @@ pluginManagement { maven("https://dl.bintray.com/kotlin/kotlinx") } - val toolsVersion = "0.9.4" + val toolsVersion = "0.9.5-dev" val kotlinVersion = "1.5.0-M2" plugins { - id("kotlinx.benchmark") version "0.2.0-dev-20" + kotlin("multiplatform") version kotlinVersion + kotlin("jvm") version kotlinVersion + kotlin("plugin.allopen") version kotlinVersion + id("org.jetbrains.kotlinx.benchmark") version "0.3.0" id("ru.mipt.npm.gradle.project") version toolsVersion id("ru.mipt.npm.gradle.mpp") version toolsVersion id("ru.mipt.npm.gradle.jvm") version toolsVersion - id("ru.mipt.npm.gradle.publish") version toolsVersion - kotlin("jvm") version kotlinVersion - kotlin("multiplatform") version kotlinVersion - kotlin("plugin.allopen") version kotlinVersion } } From a2d41d5e73e8eef1413a4f1671d0717b8b97aa9b Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 14 Apr 2021 20:30:42 +0100 Subject: [PATCH 194/393] Cholesky with precision in client API --- .../kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt | 7 ++++--- .../kotlin/space/kscience/kmath/tensors/core/checks.kt | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 82f63dd40..e0ec49333 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -66,11 +66,10 @@ public class DoubleLinearOpsTensorAlgebra : } - override fun DoubleTensor.cholesky(): DoubleTensor { - checkSymmetric(this) + public fun DoubleTensor.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) //TODO("Andrei the det routine has bugs") - //checkPositiveDefinite(this) + //checkPositiveDefinite(this, epsilon) val n = shape.last() val lTensor = zeroesLike() @@ -81,6 +80,8 @@ public class DoubleLinearOpsTensorAlgebra : return lTensor } + override fun DoubleTensor.cholesky(): DoubleTensor = cholesky(1e-6) + override fun DoubleTensor.qr(): Pair { checkSquareMatrix(shape) val qTensor = zeroesLike() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 8dbf9eb81..730b6ed9a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -63,7 +63,9 @@ internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor, eps "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } -internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor): Unit { +internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( + tensor: DoubleTensor, epsilon: Double = 1e-6): Unit { + checkSymmetric(tensor, epsilon) for( mat in tensor.matrixSequence()) check(mat.asTensor().detLU().value() > 0.0){ "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" From c7669d4fba20ccd856918504d4836d2619961927 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 14 Apr 2021 23:05:54 +0300 Subject: [PATCH 195/393] fix det --- .../core/DoubleLinearOpsTensorAlgebra.kt | 22 +++++++++---- .../kscience/kmath/tensors/core/checks.kt | 10 ++++++ .../kscience/kmath/tensors/core/linutils.kt | 11 +++++-- .../core/TestDoubleLinearOpsAlgebra.kt | 17 ++++++++-- kmath-tensors/src/jvmMain/kotlin/andMain.kt | 32 +++++++++++++++++++ 5 files changed, 81 insertions(+), 11 deletions(-) create mode 100644 kmath-tensors/src/jvmMain/kotlin/andMain.kt diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 82f63dd40..59678947a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -14,8 +14,7 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.det(): DoubleTensor = detLU() - override fun DoubleTensor.lu(): Pair { - + internal fun DoubleTensor.luForDet(forDet: Boolean = false): Pair { checkSquareMatrix(shape) val luTensor = copy() @@ -31,10 +30,22 @@ public class DoubleLinearOpsTensorAlgebra : ) for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) - luHelper(lu.as2D(), pivots.as1D(), m) + try { + luHelper(lu.as2D(), pivots.as1D(), m) + } catch (e: RuntimeException) { + if (forDet) { + lu.as2D()[intArrayOf(0, 0)] = 0.0 + } else { + throw IllegalStateException("LUP decomposition can't be performed") + } + } + return Pair(luTensor, pivotsTensor) + } + override fun DoubleTensor.lu(): Pair { + return luForDet(false) } override fun luPivot( @@ -69,8 +80,7 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.cholesky(): DoubleTensor { checkSymmetric(this) checkSquareMatrix(shape) - //TODO("Andrei the det routine has bugs") - //checkPositiveDefinite(this) + checkPositiveDefinite(this) val n = shape.last() val lTensor = zeroesLike() @@ -134,7 +144,7 @@ public class DoubleLinearOpsTensorAlgebra : } public fun DoubleTensor.detLU(): DoubleTensor { - val (luTensor, pivotsTensor) = lu() + val (luTensor, pivotsTensor) = luForDet(forDet = true) val n = shape.size val detTensorShape = IntArray(n - 1) { i -> shape[i] } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 8dbf9eb81..c61759da2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -2,6 +2,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.TensorAlgebra import space.kscience.kmath.tensors.TensorStructure +import kotlin.math.abs internal inline fun , @@ -68,4 +69,13 @@ internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite(tensor: D check(mat.asTensor().detLU().value() > 0.0){ "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" } +} + +internal inline fun DoubleLinearOpsTensorAlgebra.checkNonSingularMatrix(tensor: DoubleTensor): Unit { + for( mat in tensor.matrixSequence()) { + val detTensor = mat.asTensor().detLU() + check(!(detTensor.eq(detTensor.zeroesLike()))){ + "Tensor contains matrices which are singular" + } + } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index b3cfc1092..f2c9d8c76 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -62,10 +62,10 @@ internal inline fun dotHelper( } internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStructure1D, m: Int) { - for (row in 0 until m) pivots[row] = row + for (row in 0..m) pivots[row] = row for (i in 0 until m) { - var maxVal = -1.0 + var maxVal = 0.0 var maxInd = i for (k in i until m) { @@ -76,7 +76,9 @@ internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStru } } - //todo check singularity + if (abs(maxVal) < 1e-9) { + throw RuntimeException() + } if (maxInd != i) { @@ -158,6 +160,9 @@ internal inline fun choleskyHelper( internal inline fun luMatrixDet(luTensor: MutableStructure2D, pivotsTensor: MutableStructure1D): Double { val lu = luTensor.as2D() val pivots = pivotsTensor.as1D() + if (lu[0, 0] == 0.0) { + return 0.0 + } val m = lu.shape[0] val sign = if ((pivots[m] - m) % 2 == 0) 1.0 else -1.0 return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 37caf88fe..75ff12355 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -36,6 +36,7 @@ class TestDoubleLinearOpsTensorAlgebra { @Test fun testDet() = DoubleLinearOpsTensorAlgebra { + val expectedValue = 0.019827417 val m = fromArray( intArrayOf(3, 3), doubleArrayOf( 2.1843, 1.4391, -0.4845, @@ -43,8 +44,20 @@ class TestDoubleLinearOpsTensorAlgebra { -0.4845, 0.4055, 0.7519 ) ) - println(m.det().value()) - println(0.0197) //expected value + + assertTrue { abs(m.det().value() - expectedValue) < 1e-5} + } + + @Test + fun testDetSingle() = DoubleLinearOpsTensorAlgebra { + val expectedValue = 48.151623 + val m = fromArray( + intArrayOf(1, 1), doubleArrayOf( + expectedValue + ) + ) + + assertTrue { abs(m.det().value() - expectedValue) < 1e-5} } @Test diff --git a/kmath-tensors/src/jvmMain/kotlin/andMain.kt b/kmath-tensors/src/jvmMain/kotlin/andMain.kt new file mode 100644 index 000000000..68facf467 --- /dev/null +++ b/kmath-tensors/src/jvmMain/kotlin/andMain.kt @@ -0,0 +1,32 @@ +import space.kscience.kmath.nd.* +import space.kscience.kmath.tensors.core.DoubleLinearOpsTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.array +import kotlin.math.abs +import kotlin.math.sqrt + + +fun main() { + + DoubleTensorAlgebra { + val tensor = fromArray( + intArrayOf(2, 2, 2), + doubleArrayOf( + 1.0, 3.0, + 1.0, 2.0, + 1.5, 1.0, + 10.0, 2.0 + ) + ) + val tensor2 = fromArray( + intArrayOf(2, 2), + doubleArrayOf( + 0.0, 0.0, + 0.0, 0.0 + ) + ) + DoubleLinearOpsTensorAlgebra { + println(tensor2.det().value()) + } + } +} From aeb71b5d270f7e40f8c5b8c2416c163e6baec206 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 14 Apr 2021 23:10:42 +0300 Subject: [PATCH 196/393] fix det --- .../core/DoubleLinearOpsTensorAlgebra.kt | 28 +++++++++++++------ .../kscience/kmath/tensors/core/checks.kt | 14 +++++++++- .../kscience/kmath/tensors/core/linutils.kt | 11 ++++++-- .../core/TestDoubleLinearOpsAlgebra.kt | 17 +++++++++-- 4 files changed, 56 insertions(+), 14 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index 82f63dd40..027fcf5d0 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -14,8 +14,7 @@ public class DoubleLinearOpsTensorAlgebra : override fun DoubleTensor.det(): DoubleTensor = detLU() - override fun DoubleTensor.lu(): Pair { - + internal fun DoubleTensor.luForDet(forDet: Boolean = false): Pair { checkSquareMatrix(shape) val luTensor = copy() @@ -31,10 +30,22 @@ public class DoubleLinearOpsTensorAlgebra : ) for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) - luHelper(lu.as2D(), pivots.as1D(), m) + try { + luHelper(lu.as2D(), pivots.as1D(), m) + } catch (e: RuntimeException) { + if (forDet) { + lu.as2D()[intArrayOf(0, 0)] = 0.0 + } else { + throw IllegalStateException("LUP decomposition can't be performed") + } + } + return Pair(luTensor, pivotsTensor) + } + override fun DoubleTensor.lu(): Pair { + return luForDet(false) } override fun luPivot( @@ -66,11 +77,10 @@ public class DoubleLinearOpsTensorAlgebra : } - override fun DoubleTensor.cholesky(): DoubleTensor { - checkSymmetric(this) + public fun DoubleTensor.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) - //TODO("Andrei the det routine has bugs") - //checkPositiveDefinite(this) + checkPositiveDefinite(this) + //checkPositiveDefinite(this, epsilon) val n = shape.last() val lTensor = zeroesLike() @@ -81,6 +91,8 @@ public class DoubleLinearOpsTensorAlgebra : return lTensor } + override fun DoubleTensor.cholesky(): DoubleTensor = cholesky(1e-6) + override fun DoubleTensor.qr(): Pair { checkSquareMatrix(shape) val qTensor = zeroesLike() @@ -134,7 +146,7 @@ public class DoubleLinearOpsTensorAlgebra : } public fun DoubleTensor.detLU(): DoubleTensor { - val (luTensor, pivotsTensor) = lu() + val (luTensor, pivotsTensor) = luForDet(forDet = true) val n = shape.size val detTensorShape = IntArray(n - 1) { i -> shape[i] } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 8dbf9eb81..45a71d1bc 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -2,6 +2,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.TensorAlgebra import space.kscience.kmath.tensors.TensorStructure +import kotlin.math.abs internal inline fun , @@ -63,9 +64,20 @@ internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor, eps "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } -internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor): Unit { +internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( + tensor: DoubleTensor, epsilon: Double = 1e-6): Unit { + checkSymmetric(tensor, epsilon) for( mat in tensor.matrixSequence()) check(mat.asTensor().detLU().value() > 0.0){ "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" } +} + +internal inline fun DoubleLinearOpsTensorAlgebra.checkNonSingularMatrix(tensor: DoubleTensor): Unit { + for( mat in tensor.matrixSequence()) { + val detTensor = mat.asTensor().detLU() + check(!(detTensor.eq(detTensor.zeroesLike()))){ + "Tensor contains matrices which are singular" + } + } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index b3cfc1092..f2c9d8c76 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -62,10 +62,10 @@ internal inline fun dotHelper( } internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStructure1D, m: Int) { - for (row in 0 until m) pivots[row] = row + for (row in 0..m) pivots[row] = row for (i in 0 until m) { - var maxVal = -1.0 + var maxVal = 0.0 var maxInd = i for (k in i until m) { @@ -76,7 +76,9 @@ internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStru } } - //todo check singularity + if (abs(maxVal) < 1e-9) { + throw RuntimeException() + } if (maxInd != i) { @@ -158,6 +160,9 @@ internal inline fun choleskyHelper( internal inline fun luMatrixDet(luTensor: MutableStructure2D, pivotsTensor: MutableStructure1D): Double { val lu = luTensor.as2D() val pivots = pivotsTensor.as1D() + if (lu[0, 0] == 0.0) { + return 0.0 + } val m = lu.shape[0] val sign = if ((pivots[m] - m) % 2 == 0) 1.0 else -1.0 return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 37caf88fe..75ff12355 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -36,6 +36,7 @@ class TestDoubleLinearOpsTensorAlgebra { @Test fun testDet() = DoubleLinearOpsTensorAlgebra { + val expectedValue = 0.019827417 val m = fromArray( intArrayOf(3, 3), doubleArrayOf( 2.1843, 1.4391, -0.4845, @@ -43,8 +44,20 @@ class TestDoubleLinearOpsTensorAlgebra { -0.4845, 0.4055, 0.7519 ) ) - println(m.det().value()) - println(0.0197) //expected value + + assertTrue { abs(m.det().value() - expectedValue) < 1e-5} + } + + @Test + fun testDetSingle() = DoubleLinearOpsTensorAlgebra { + val expectedValue = 48.151623 + val m = fromArray( + intArrayOf(1, 1), doubleArrayOf( + expectedValue + ) + ) + + assertTrue { abs(m.det().value() - expectedValue) < 1e-5} } @Test From e2ceb64d36058b7f1fddd6fdc0b3ea4e5adc61fb Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 14 Apr 2021 23:26:21 +0300 Subject: [PATCH 197/393] Fix errors and migrations --- CHANGELOG.md | 3 + examples/build.gradle.kts | 5 +- kmath-core/api/kmath-core.api | 1188 ++--------------- .../kmath/domains/UnivariateDomain.kt | 2 +- .../FunctionalExpressionAlgebra.kt | 4 +- .../kscience/kmath/expressions/MstAlgebra.kt | 2 +- .../kmath/expressions/SymbolIndexer.kt | 4 +- .../kmath/expressions/expressionBuilders.kt | 5 +- .../space/kscience/kmath/misc/Symbol.kt | 4 +- .../space/kscience/kmath/misc/cumulative.kt | 8 +- .../kscience/kmath/nd/BufferAlgebraND.kt | 4 +- .../space/kscience/kmath/nd/Structure1D.kt | 7 +- .../space/kscience/kmath/nd/Structure2D.kt | 4 +- .../kmath/operations/AlgebraElements.kt | 6 +- .../space/kscience/kmath/operations/BigInt.kt | 4 +- .../kmath/operations/NumericAlgebra.kt | 2 +- .../kmath/operations/algebraExtensions.kt | 30 +- .../space/kscience/kmath/structures/Buffer.kt | 14 +- .../kscience/kmath/structures/DoubleBuffer.kt | 6 +- .../kscience/kmath/structures/FloatBuffer.kt | 5 +- .../kscience/kmath/structures/IntBuffer.kt | 5 +- .../kscience/kmath/structures/LongBuffer.kt | 5 +- .../kscience/kmath/structures/ShortBuffer.kt | 5 +- .../kmath/structures/bufferOperation.kt | 16 +- .../kscience/kmath/testutils/SpaceVerifier.kt | 4 +- .../space/kscience/kmath/chains/flowExtra.kt | 4 +- .../kscience/kmath/dimensions/Wrappers.kt | 10 +- .../kscience/kmath/functions/Polynomial.kt | 2 +- .../kmath/integration/GaussIntegrator.kt | 65 + .../integration/GaussIntegratorRuleFactory.kt | 166 +++ .../kmath/geometry/Euclidean2DSpace.kt | 4 +- .../kmath/geometry/Euclidean3DSpace.kt | 4 +- .../space/kscience/kmath/histogram/Counter.kt | 4 +- .../kmath/histogram/IndexedHistogramSpace.kt | 4 +- .../kmath/histogram/UnivariateHistogram.kt | 4 +- .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 2 +- .../kmath/distributions/NormalDistribution.kt | 2 +- .../kotlin/space/kscience/kmath/stat/Mean.kt | 2 +- kmath-viktor/api/kmath-viktor.api | 71 - settings.gradle.kts | 11 +- 40 files changed, 457 insertions(+), 1240 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index c7fe7eed2..f7acd08cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ - Basic integration API - Basic MPP distributions and samplers - bindSymbolOrNull +- Blocking chains and Statistics +- Multiplatform integration ### Changed - Exponential operations merged with hyperbolic functions @@ -29,6 +31,7 @@ - MSTExpression ### Fixed +- Ring inherits RingOperations, not GroupOperations ### Security diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 3fc2ec7f0..d02e5268e 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -114,7 +114,10 @@ kotlin.sourceSets.all { } tasks.withType { - kotlinOptions.jvmTarget = "11" + kotlinOptions{ + jvmTarget = "11" + freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + } } readme { diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 08aa1bbe4..c62abbf12 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -1,18 +1,10 @@ public final class space/kscience/kmath/data/ColumnarDataKt { } -public final class space/kscience/kmath/data/XYColumnarData$DefaultImpls { - public static fun get (Lspace/kscience/kmath/data/XYColumnarData;Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer; -} - public final class space/kscience/kmath/data/XYColumnarDataKt { public static synthetic fun asXYData$default (Lspace/kscience/kmath/nd/Structure2D;IIILjava/lang/Object;)Lspace/kscience/kmath/data/XYColumnarData; } -public final class space/kscience/kmath/data/XYZColumnarData$DefaultImpls { - public static fun get (Lspace/kscience/kmath/data/XYZColumnarData;Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer; -} - public abstract interface class space/kscience/kmath/domains/Domain { public abstract fun contains (Lspace/kscience/kmath/structures/Buffer;)Z public abstract fun getDimension ()I @@ -53,20 +45,11 @@ public abstract interface class space/kscience/kmath/expressions/ExpressionAlgeb public abstract fun const (Ljava/lang/Object;)Ljava/lang/Object; } -public final class space/kscience/kmath/expressions/ExpressionAlgebra$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Ljava/lang/String;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; -} - public final class space/kscience/kmath/expressions/ExpressionBuildersKt { public static final fun extendedFieldExpression (Lspace/kscience/kmath/operations/ExtendedField;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; public static final fun fieldExpression (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; public static final fun ringExpression (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; - public static final fun spaceExpression (Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; + public static final fun spaceExpression (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; } public final class space/kscience/kmath/expressions/ExpressionKt { @@ -84,18 +67,12 @@ public abstract class space/kscience/kmath/expressions/FirstDerivativeExpression public abstract class space/kscience/kmath/expressions/FunctionalExpressionAlgebra : space/kscience/kmath/expressions/ExpressionAlgebra { public fun (Lspace/kscience/kmath/operations/Algebra;)V - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun const (Ljava/lang/Object;)Ljava/lang/Object; public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression; public final fun getAlgebra ()Lspace/kscience/kmath/operations/Algebra; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -103,51 +80,34 @@ public final class space/kscience/kmath/expressions/FunctionalExpressionAlgebraK public static final fun expressionInExtendedField (Lspace/kscience/kmath/operations/ExtendedField;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; public static final fun expressionInField (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; public static final fun expressionInRing (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; - public static final fun expressionInSpace (Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; + public static final fun expressionInSpace (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; } public class space/kscience/kmath/expressions/FunctionalExpressionExtendedField : space/kscience/kmath/expressions/FunctionalExpressionField, space/kscience/kmath/operations/ExtendedField { public fun (Lspace/kscience/kmath/operations/ExtendedField;)V public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; public fun acos (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun acosh (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; public fun asin (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun asinh (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; public fun atan (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun atanh (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cos (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun cosh (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; public fun exp (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; public fun ln (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sin (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun sinh (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; public fun sqrt (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; - public fun tan (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun tanh (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -156,28 +116,12 @@ public class space/kscience/kmath/expressions/FunctionalExpressionField : space/ public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public final fun div (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public fun div (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; public final fun div (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression; - public fun div (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/expressions/Expression;D)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/Expression; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -188,19 +132,13 @@ public class space/kscience/kmath/expressions/FunctionalExpressionGroup : space/ public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/expressions/Expression; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public final fun minus (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public final fun minus (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression; - public fun minus (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public final fun plus (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public final fun plus (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression; - public fun plus (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; } public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/kscience/kmath/expressions/FunctionalExpressionGroup, space/kscience/kmath/operations/Ring { @@ -210,10 +148,8 @@ public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/k public fun getOne ()Lspace/kscience/kmath/expressions/Expression; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public final fun times (Ljava/lang/Object;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public final fun times (Lspace/kscience/kmath/expressions/Expression;Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression; - public fun times (Lspace/kscience/kmath/expressions/Expression;Lspace/kscience/kmath/expressions/Expression;)Lspace/kscience/kmath/expressions/Expression; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -279,23 +215,13 @@ public final class space/kscience/kmath/expressions/MSTKt { public final class space/kscience/kmath/expressions/MstAlgebra : space/kscience/kmath/operations/NumericAlgebra { public static final field INSTANCE Lspace/kscience/kmath/expressions/MstAlgebra; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -315,21 +241,13 @@ public final class space/kscience/kmath/expressions/MstExtendedField : space/ksc public fun atan (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; public fun atanh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST; public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cos (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun cosh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; - public fun div (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; @@ -338,9 +256,6 @@ public final class space/kscience/kmath/expressions/MstExtendedField : space/ksc public fun getOne ()Lspace/kscience/kmath/expressions/MST$Numeric; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; public fun ln (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -349,37 +264,20 @@ public final class space/kscience/kmath/expressions/MstExtendedField : space/ksc public fun multiply (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Binary; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/expressions/MST;D)Lspace/kscience/kmath/expressions/MST; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sin (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; - public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; public fun tan (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; public fun tanh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; - public fun times (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; @@ -389,57 +287,25 @@ public final class space/kscience/kmath/expressions/MstField : space/kscience/km public static final field INSTANCE Lspace/kscience/kmath/expressions/MstField; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST; public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; - public fun div (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/expressions/MST$Numeric; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; public fun minus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; - public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; - public fun plus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/expressions/MST;D)Lspace/kscience/kmath/expressions/MST$Binary; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; - public fun times (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; @@ -449,39 +315,19 @@ public final class space/kscience/kmath/expressions/MstGroup : space/kscience/km public static final field INSTANCE Lspace/kscience/kmath/expressions/MstGroup; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST; public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/expressions/MST;D)Lspace/kscience/kmath/expressions/MST$Binary; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; @@ -491,53 +337,23 @@ public final class space/kscience/kmath/expressions/MstRing : space/kscience/kma public static final field INSTANCE Lspace/kscience/kmath/expressions/MstRing; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST; public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/expressions/MST$Numeric; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; public fun minus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; - public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; - public fun plus (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/expressions/MST;D)Lspace/kscience/kmath/expressions/MST$Binary; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/expressions/MST;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST; - public fun times (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; @@ -577,12 +393,9 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffExtendedField public fun ln (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; public final fun pow (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/expressions/AutoDiffValue;D)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; @@ -596,28 +409,18 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffExtendedField public fun tan (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; public fun tanh (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscience/kmath/expressions/ExpressionAlgebra, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumbersAddOperations { public fun (Lspace/kscience/kmath/operations/Field;Ljava/util/Map;)V public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun const (Ljava/lang/Object;)Ljava/lang/Object; public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/AutoDiffValue; public final fun const (Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/AutoDiffValue; public final fun derive (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public fun div (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public final fun getContext ()Lspace/kscience/kmath/operations/Field; @@ -626,44 +429,15 @@ public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscien public fun getOne ()Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/expressions/AutoDiffValue; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public fun minus (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public fun plus (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/expressions/AutoDiffValue;D)Lspace/kscience/kmath/expressions/AutoDiffValue; public final fun setD (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Object;)V - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/expressions/AutoDiffValue;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public fun times (Lspace/kscience/kmath/expressions/AutoDiffValue;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; } public final class space/kscience/kmath/expressions/SimpleAutoDiffKt { @@ -692,19 +466,6 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt { public static final fun tanh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; } -public final class space/kscience/kmath/expressions/SymbolIndexer$DefaultImpls { - public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/List;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; - public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/misc/Symbol;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; - public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; - public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;[DLspace/kscience/kmath/misc/Symbol;)D - public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;[Ljava/lang/Object;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; - public static fun indexOf (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/misc/Symbol;)I - public static fun toDoubleArray (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/Map;)[D - public static fun toList (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/Map;)Ljava/util/List; - public static fun toMap (Lspace/kscience/kmath/expressions/SymbolIndexer;[D)Ljava/util/Map; - public static fun toPoint (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/Map;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; -} - public final class space/kscience/kmath/expressions/SymbolIndexerKt { } @@ -716,15 +477,9 @@ public final class space/kscience/kmath/linear/BufferedLinearSpace : space/kscie public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public fun getElementAlgebra ()Lspace/kscience/kmath/operations/Ring; public fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun times (Ljava/lang/Object;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; - public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; public fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; } public abstract interface class space/kscience/kmath/linear/CholeskyDecompositionFeature : space/kscience/kmath/linear/MatrixFeature { @@ -753,11 +508,7 @@ public final class space/kscience/kmath/linear/LFeature : space/kscience/kmath/l public abstract interface class space/kscience/kmath/linear/LinearSolver { public abstract fun inverse (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public abstract fun solve (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun solve (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; -} - -public final class space/kscience/kmath/linear/LinearSolver$DefaultImpls { - public static fun solve (Lspace/kscience/kmath/linear/LinearSolver;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun solve (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; } public final class space/kscience/kmath/linear/LinearSolverKt { @@ -769,19 +520,19 @@ public abstract interface class space/kscience/kmath/linear/LinearSpace { public static final field Companion Lspace/kscience/kmath/linear/LinearSpace$Companion; public abstract fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D; public abstract fun buildVector (ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public abstract fun getElementAlgebra ()Lspace/kscience/kmath/operations/Ring; - public abstract fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public abstract fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun minus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun times (Ljava/lang/Object;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public fun times (Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; + public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; + public fun unaryMinus (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; + public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; } public final class space/kscience/kmath/linear/LinearSpace$Companion { @@ -790,21 +541,6 @@ public final class space/kscience/kmath/linear/LinearSpace$Companion { public final fun getReal ()Lspace/kscience/kmath/linear/LinearSpace; } -public final class space/kscience/kmath/linear/LinearSpace$DefaultImpls { - public static fun dot (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun dot (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun minus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun minus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun plus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun plus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun times (Lspace/kscience/kmath/linear/LinearSpace;Ljava/lang/Object;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun times (Lspace/kscience/kmath/linear/LinearSpace;Ljava/lang/Object;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static fun times (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; - public static fun times (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; - public static fun unaryMinus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; - public static fun unaryMinus (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; -} - public final class space/kscience/kmath/linear/LinearSpaceKt { public static final fun invoke (Lspace/kscience/kmath/linear/LinearSpace;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } @@ -913,15 +649,10 @@ public final class space/kscience/kmath/linear/UnitFeature : space/kscience/kmat public final class space/kscience/kmath/linear/VirtualMatrix : space/kscience/kmath/nd/Structure2D { public fun (IILkotlin/jvm/functions/Function2;)V - public fun elements ()Lkotlin/sequences/Sequence; public fun get (II)Ljava/lang/Object; - public fun get ([I)Ljava/lang/Object; public fun getColNum ()I - public fun getColumns ()Ljava/util/List; - public fun getDimension ()I public final fun getGenerator ()Lkotlin/jvm/functions/Function2; public fun getRowNum ()I - public fun getRows ()Ljava/util/List; public fun getShape ()[I } @@ -934,9 +665,9 @@ public final class space/kscience/kmath/misc/CumulativeKt { public static final fun cumulative (Ljava/util/Iterator;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/util/Iterator; public static final fun cumulative (Ljava/util/List;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public static final fun cumulative (Lkotlin/sequences/Sequence;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Lkotlin/sequences/Sequence; - public static final fun cumulativeSum (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Iterable; - public static final fun cumulativeSum (Ljava/util/List;Lspace/kscience/kmath/operations/Group;)Ljava/util/List; - public static final fun cumulativeSum (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Group;)Lkotlin/sequences/Sequence; + public static final fun cumulativeSum (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Ring;)Ljava/lang/Iterable; + public static final fun cumulativeSum (Ljava/util/List;Lspace/kscience/kmath/operations/Ring;)Ljava/util/List; + public static final fun cumulativeSum (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Ring;)Lkotlin/sequences/Sequence; public static final fun cumulativeSumOfDouble (Ljava/lang/Iterable;)Ljava/lang/Iterable; public static final fun cumulativeSumOfDouble (Ljava/util/List;)Ljava/util/List; public static final fun cumulativeSumOfDouble (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; @@ -985,7 +716,7 @@ public abstract interface class space/kscience/kmath/nd/AlgebraND { public abstract fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public abstract fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; public abstract fun getShape ()[I - public abstract fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public abstract fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public abstract fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; @@ -994,34 +725,25 @@ public abstract interface class space/kscience/kmath/nd/AlgebraND { public final class space/kscience/kmath/nd/AlgebraND$Companion { } -public final class space/kscience/kmath/nd/AlgebraND$DefaultImpls { - public static fun invoke (Lspace/kscience/kmath/nd/AlgebraND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; -} - public abstract interface class space/kscience/kmath/nd/BufferAlgebraND : space/kscience/kmath/nd/AlgebraND { - public abstract fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; - public abstract fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; + public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; + public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; + public fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; public abstract fun getBufferFactory ()Lkotlin/jvm/functions/Function2; public abstract fun getStrides ()Lspace/kscience/kmath/nd/Strides; - public abstract fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; - public abstract fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; - public abstract fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; -} - -public final class space/kscience/kmath/nd/BufferAlgebraND$DefaultImpls { - public static fun combine (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; - public static fun getBuffer (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; - public static fun invoke (Lspace/kscience/kmath/nd/BufferAlgebraND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun map (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; - public static fun mapIndexed (Lspace/kscience/kmath/nd/BufferAlgebraND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; - public static fun produce (Lspace/kscience/kmath/nd/BufferAlgebraND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; + public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; + public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; + public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; + public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; + public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; + public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; } public final class space/kscience/kmath/nd/BufferAlgebraNDKt { public static final fun field (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedFieldND; - public static final fun group (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedGroupND; + public static final fun group (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedGroupND; public static final fun ndField (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun ndGroup (Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun ndGroup (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun ndRing (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun ring (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedRingND; } @@ -1031,7 +753,6 @@ public final class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/St public fun elements ()Lkotlin/sequences/Sequence; public fun get ([I)Ljava/lang/Object; public final fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; - public fun getDimension ()I public fun getShape ()[I public final fun getStrides ()Lspace/kscience/kmath/nd/Strides; public fun toString ()Ljava/lang/String; @@ -1039,47 +760,12 @@ public final class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/St public class space/kscience/kmath/nd/BufferedFieldND : space/kscience/kmath/nd/BufferedRingND, space/kscience/kmath/nd/FieldND { public fun ([ILspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;)V - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public fun div (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun divide (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; } public class space/kscience/kmath/nd/BufferedGroupND : space/kscience/kmath/nd/BufferAlgebraND, space/kscience/kmath/nd/GroupND { public fun ([ILspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function2;)V - public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun add (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; - public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; - public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; - public fun getBuffer (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/structures/Buffer; public final fun getBufferFactory ()Lkotlin/jvm/functions/Function2; public synthetic fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; public final fun getElementContext ()Lspace/kscience/kmath/operations/Group; @@ -1087,41 +773,14 @@ public class space/kscience/kmath/nd/BufferedGroupND : space/kscience/kmath/nd/B public fun getStrides ()Lspace/kscience/kmath/nd/Strides; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/nd/BufferND; - public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; - public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; - public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; - public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public fun minus (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public fun plus (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; - public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } public class space/kscience/kmath/nd/BufferedRingND : space/kscience/kmath/nd/BufferedGroupND, space/kscience/kmath/nd/RingND { public fun ([ILspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/nd/BufferND; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public fun times (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath/nd/Strides { @@ -1133,7 +792,6 @@ public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath public fun getStrides ()Ljava/util/List; public fun hashCode ()I public fun index (I)[I - public fun indices ()Lkotlin/sequences/Sequence; public fun offset ([I)I } @@ -1155,8 +813,6 @@ public final class space/kscience/kmath/nd/DoubleFieldND : space/kscience/kmath/ public fun atan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; public fun atanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; @@ -1177,37 +833,22 @@ public final class space/kscience/kmath/nd/DoubleFieldND : space/kscience/kmath/ public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/BufferND; - public synthetic fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/BufferND; public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; - public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; public fun tanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } public final class space/kscience/kmath/nd/DoubleFieldNDKt { @@ -1216,115 +857,40 @@ public final class space/kscience/kmath/nd/DoubleFieldNDKt { } public abstract interface class space/kscience/kmath/nd/FieldND : space/kscience/kmath/nd/RingND, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/ScaleOperations { - public abstract fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public abstract fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public abstract fun divide (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; -} - -public final class space/kscience/kmath/nd/FieldND$DefaultImpls { - public static fun add (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun binaryOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; - public static fun div (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun div (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public static fun div (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public static fun div (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun divide (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun invoke (Lspace/kscience/kmath/nd/FieldND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun leftSideNumberOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun minus (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun minus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public static fun minus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun multiply (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun number (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public static fun plus (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun plus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public static fun plus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun rightSideNumberOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun times (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun times (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun times (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public static fun times (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public static fun times (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun unaryOperation (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/FieldND;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/nd/FieldND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun divide (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } public abstract interface class space/kscience/kmath/nd/GroupND : space/kscience/kmath/nd/AlgebraND, space/kscience/kmath/operations/Group { public static final field Companion Lspace/kscience/kmath/nd/GroupND$Companion; - public abstract fun add (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public abstract fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public abstract fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public abstract fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public abstract fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun add (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; } public final class space/kscience/kmath/nd/GroupND$Companion { } -public final class space/kscience/kmath/nd/GroupND$DefaultImpls { - public static fun add (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun binaryOperation (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; - public static fun invoke (Lspace/kscience/kmath/nd/GroupND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun minus (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun minus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public static fun minus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun plus (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun plus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public static fun plus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun unaryOperation (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/GroupND;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/nd/GroupND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; -} - public abstract interface class space/kscience/kmath/nd/MutableStructureND : space/kscience/kmath/nd/StructureND { public abstract fun set ([ILjava/lang/Object;)V } -public final class space/kscience/kmath/nd/MutableStructureND$DefaultImpls { - public static fun getDimension (Lspace/kscience/kmath/nd/MutableStructureND;)I -} - public abstract interface class space/kscience/kmath/nd/RingND : space/kscience/kmath/nd/GroupND, space/kscience/kmath/operations/Ring { public static final field Companion Lspace/kscience/kmath/nd/RingND$Companion; - public abstract fun multiply (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public abstract fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public abstract fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun multiply (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; + public fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; } public final class space/kscience/kmath/nd/RingND$Companion { } -public final class space/kscience/kmath/nd/RingND$DefaultImpls { - public static fun add (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun binaryOperation (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun binaryOperationFunction (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; - public static fun invoke (Lspace/kscience/kmath/nd/RingND;Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun minus (Lspace/kscience/kmath/nd/RingND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun minus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public static fun minus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun multiply (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun plus (Lspace/kscience/kmath/nd/RingND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun plus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public static fun plus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun times (Lspace/kscience/kmath/nd/RingND;Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun times (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public static fun times (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun unaryOperation (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public static fun unaryOperationFunction (Lspace/kscience/kmath/nd/RingND;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/nd/RingND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; -} - public final class space/kscience/kmath/nd/ShapeMismatchException : java/lang/RuntimeException { public fun ([I[I)V public final fun getActual ()[I @@ -1333,28 +899,12 @@ public final class space/kscience/kmath/nd/ShapeMismatchException : java/lang/Ru public final class space/kscience/kmath/nd/ShortRingND : space/kscience/kmath/nd/BufferedRingND, space/kscience/kmath/operations/NumbersAddOperations { public fun ([I)V - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/nd/BufferND; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/nd/BufferND; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/BufferND; - public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; } public final class space/kscience/kmath/nd/ShortRingNDKt { @@ -1367,30 +917,20 @@ public abstract interface class space/kscience/kmath/nd/Strides { public abstract fun getShape ()[I public abstract fun getStrides ()Ljava/util/List; public abstract fun index (I)[I - public abstract fun indices ()Lkotlin/sequences/Sequence; + public fun indices ()Lkotlin/sequences/Sequence; public abstract fun offset ([I)I } -public final class space/kscience/kmath/nd/Strides$DefaultImpls { - public static fun indices (Lspace/kscience/kmath/nd/Strides;)Lkotlin/sequences/Sequence; -} - public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/StructureND, space/kscience/kmath/structures/Buffer { public static final field Companion Lspace/kscience/kmath/nd/Structure1D$Companion; - public abstract fun get ([I)Ljava/lang/Object; - public abstract fun getDimension ()I - public abstract fun iterator ()Ljava/util/Iterator; + public fun get ([I)Ljava/lang/Object; + public fun getDimension ()I + public fun iterator ()Ljava/util/Iterator; } public final class space/kscience/kmath/nd/Structure1D$Companion { } -public final class space/kscience/kmath/nd/Structure1D$DefaultImpls { - public static fun get (Lspace/kscience/kmath/nd/Structure1D;[I)Ljava/lang/Object; - public static fun getDimension (Lspace/kscience/kmath/nd/Structure1D;)I - public static fun iterator (Lspace/kscience/kmath/nd/Structure1D;)Ljava/util/Iterator; -} - public final class space/kscience/kmath/nd/Structure1DKt { public static final fun as1D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure1D; public static final fun asND (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/nd/Structure1D; @@ -1398,28 +938,19 @@ public final class space/kscience/kmath/nd/Structure1DKt { public abstract interface class space/kscience/kmath/nd/Structure2D : space/kscience/kmath/nd/StructureND { public static final field Companion Lspace/kscience/kmath/nd/Structure2D$Companion; - public abstract fun elements ()Lkotlin/sequences/Sequence; + public fun elements ()Lkotlin/sequences/Sequence; public abstract fun get (II)Ljava/lang/Object; - public abstract fun get ([I)Ljava/lang/Object; + public fun get ([I)Ljava/lang/Object; public abstract fun getColNum ()I - public abstract fun getColumns ()Ljava/util/List; + public fun getColumns ()Ljava/util/List; public abstract fun getRowNum ()I - public abstract fun getRows ()Ljava/util/List; - public abstract fun getShape ()[I + public fun getRows ()Ljava/util/List; + public fun getShape ()[I } public final class space/kscience/kmath/nd/Structure2D$Companion { } -public final class space/kscience/kmath/nd/Structure2D$DefaultImpls { - public static fun elements (Lspace/kscience/kmath/nd/Structure2D;)Lkotlin/sequences/Sequence; - public static fun get (Lspace/kscience/kmath/nd/Structure2D;[I)Ljava/lang/Object; - public static fun getColumns (Lspace/kscience/kmath/nd/Structure2D;)Ljava/util/List; - public static fun getDimension (Lspace/kscience/kmath/nd/Structure2D;)I - public static fun getRows (Lspace/kscience/kmath/nd/Structure2D;)Ljava/util/List; - public static fun getShape (Lspace/kscience/kmath/nd/Structure2D;)[I -} - public final class space/kscience/kmath/nd/Structure2DKt { public static final fun as2D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure2D; } @@ -1431,7 +962,7 @@ public abstract interface class space/kscience/kmath/nd/StructureND { public static final field Companion Lspace/kscience/kmath/nd/StructureND$Companion; public abstract fun elements ()Lkotlin/sequences/Sequence; public abstract fun get ([I)Ljava/lang/Object; - public abstract fun getDimension ()I + public fun getDimension ()I public abstract fun getShape ()[I } @@ -1446,31 +977,18 @@ public final class space/kscience/kmath/nd/StructureND$Companion { public final fun toString (Lspace/kscience/kmath/nd/StructureND;)Ljava/lang/String; } -public final class space/kscience/kmath/nd/StructureND$DefaultImpls { - public static fun getDimension (Lspace/kscience/kmath/nd/StructureND;)I -} - public final class space/kscience/kmath/nd/StructureNDKt { public static final fun get (Lspace/kscience/kmath/nd/StructureND;[I)Ljava/lang/Object; public static final fun mapInPlace (Lspace/kscience/kmath/nd/MutableStructureND;Lkotlin/jvm/functions/Function2;)V } public abstract interface class space/kscience/kmath/operations/Algebra { - public abstract fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public abstract fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public abstract fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public abstract fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; -} - -public final class space/kscience/kmath/operations/Algebra$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/Algebra;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Algebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Algebra;Ljava/lang/String;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/Algebra;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Algebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } public abstract interface class space/kscience/kmath/operations/AlgebraElement { @@ -1484,17 +1002,17 @@ public final class space/kscience/kmath/operations/AlgebraElementsKt { } public final class space/kscience/kmath/operations/AlgebraExtensionsKt { - public static final fun abs (Lspace/kscience/kmath/operations/Group;Ljava/lang/Comparable;)Ljava/lang/Comparable; - public static final fun average (Lspace/kscience/kmath/operations/Group;Ljava/lang/Iterable;)Ljava/lang/Object; - public static final fun average (Lspace/kscience/kmath/operations/Group;Lkotlin/sequences/Sequence;)Ljava/lang/Object; - public static final fun averageWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object; - public static final fun averageWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object; + public static final fun abs (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Comparable;)Ljava/lang/Comparable; + public static final fun average (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Iterable;)Ljava/lang/Object; + public static final fun average (Lspace/kscience/kmath/operations/Ring;Lkotlin/sequences/Sequence;)Ljava/lang/Object; + public static final fun averageWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Ring;)Ljava/lang/Object; + public static final fun averageWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Ring;)Ljava/lang/Object; public static final fun power (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;I)Ljava/lang/Object; public static final fun power (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;I)Ljava/lang/Object; - public static final fun sum (Lspace/kscience/kmath/operations/Group;Ljava/lang/Iterable;)Ljava/lang/Object; - public static final fun sum (Lspace/kscience/kmath/operations/Group;Lkotlin/sequences/Sequence;)Ljava/lang/Object; - public static final fun sumWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object; - public static final fun sumWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object; + public static final fun sum (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Iterable;)Ljava/lang/Object; + public static final fun sum (Lspace/kscience/kmath/operations/Ring;Lkotlin/sequences/Sequence;)Ljava/lang/Object; + public static final fun sumWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Ring;)Ljava/lang/Object; + public static final fun sumWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Ring;)Ljava/lang/Object; } public final class space/kscience/kmath/operations/AlgebraKt { @@ -1540,62 +1058,22 @@ public final class space/kscience/kmath/operations/BigIntField : space/kscience/ public static final field INSTANCE Lspace/kscience/kmath/operations/BigIntField; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/operations/BigInt; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/operations/BigInt; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt; - public fun div (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/operations/BigInt; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/operations/BigInt; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt; - public fun minus (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt; - public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt; - public fun plus (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/operations/BigInt;D)Lspace/kscience/kmath/operations/BigInt; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/operations/BigInt;Ljava/lang/Number;)Lspace/kscience/kmath/operations/BigInt; - public fun times (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public final fun unaryMinus (Ljava/lang/String;)Lspace/kscience/kmath/operations/BigInt; public fun unaryMinus (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; public final fun unaryPlus (Ljava/lang/String;)Lspace/kscience/kmath/operations/BigInt; - public fun unaryPlus (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; } public final class space/kscience/kmath/operations/BigIntKt { @@ -1615,20 +1093,10 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma public static final field INSTANCE Lspace/kscience/kmath/operations/ByteRing; public fun add (BB)Ljava/lang/Byte; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;BB)Ljava/lang/Byte; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Byte; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Byte; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun getOne ()Ljava/lang/Byte; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Byte; public synthetic fun getZero ()Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;B)Ljava/lang/Byte; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun minus (BB)Ljava/lang/Byte; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (BB)Ljava/lang/Byte; @@ -1639,18 +1107,10 @@ public final class space/kscience/kmath/operations/ByteRing : space/kscience/kma public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun plus (BB)Ljava/lang/Byte; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;BLjava/lang/Number;)Ljava/lang/Byte; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun times (BB)Ljava/lang/Byte; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (B)Ljava/lang/Byte; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;B)Ljava/lang/Byte; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public fun unaryPlus (B)Ljava/lang/Byte; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; } public final class space/kscience/kmath/operations/DoubleField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/ScaleOperations { @@ -1669,20 +1129,12 @@ public final class space/kscience/kmath/operations/DoubleField : space/kscience/ public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; public fun atanh (D)Ljava/lang/Double; public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;DD)Ljava/lang/Double; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Double; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Double; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun cos (D)Ljava/lang/Double; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cosh (D)Ljava/lang/Double; public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun div (DD)Ljava/lang/Double; - public fun div (DLjava/lang/Number;)Ljava/lang/Double; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (DD)Ljava/lang/Double; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -1692,9 +1144,6 @@ public final class space/kscience/kmath/operations/DoubleField : space/kscience/ public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Double; public synthetic fun getZero ()Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;D)Ljava/lang/Double; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun ln (D)Ljava/lang/Double; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; public fun minus (DD)Ljava/lang/Double; @@ -1707,38 +1156,22 @@ public final class space/kscience/kmath/operations/DoubleField : space/kscience/ public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun plus (DD)Ljava/lang/Double; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun pow (DLjava/lang/Number;)Ljava/lang/Double; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power (DLjava/lang/Number;)Ljava/lang/Double; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;DLjava/lang/Number;)Ljava/lang/Double; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun scale (DD)Ljava/lang/Double; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun sin (D)Ljava/lang/Double; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh (D)Ljava/lang/Double; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (D)Ljava/lang/Double; - public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; public fun tan (D)Ljava/lang/Double; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; public fun tanh (D)Ljava/lang/Double; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; public fun times (DD)Ljava/lang/Double; - public fun times (DLjava/lang/Number;)Ljava/lang/Double; - public fun times (Ljava/lang/Number;D)Ljava/lang/Double; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (D)Ljava/lang/Double; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;D)Ljava/lang/Double; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public fun unaryPlus (D)Ljava/lang/Double; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; } public abstract interface class space/kscience/kmath/operations/ExponentialOperations : space/kscience/kmath/operations/Algebra { @@ -1772,112 +1205,32 @@ public final class space/kscience/kmath/operations/ExponentialOperations$Compani public static final field TANH_OPERATION Ljava/lang/String; } -public final class space/kscience/kmath/operations/ExponentialOperations$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ExponentialOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; -} - public abstract interface class space/kscience/kmath/operations/ExtendedField : space/kscience/kmath/operations/ExtendedFieldOperations, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/ScaleOperations { - public abstract fun acosh (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun asinh (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public abstract fun cosh (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public abstract fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun tanh (Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class space/kscience/kmath/operations/ExtendedField$DefaultImpls { - public static fun acosh (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; - public static fun asinh (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; - public static fun atanh (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperation (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Ljava/lang/Object; - public static fun cosh (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun minus (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun number (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Number;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun pow (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun sinh (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; - public static fun sqrt (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; - public static fun tan (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; - public static fun tanh (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/operations/ExtendedField;Ljava/lang/Object;)Ljava/lang/Object; + public fun acosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun asinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun atanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun cosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public fun sinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun tanh (Ljava/lang/Object;)Ljava/lang/Object; } public abstract interface class space/kscience/kmath/operations/ExtendedFieldOperations : space/kscience/kmath/operations/ExponentialOperations, space/kscience/kmath/operations/FieldOperations, space/kscience/kmath/operations/PowerOperations, space/kscience/kmath/operations/TrigonometricOperations { - public abstract fun tan (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun tanh (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; -} - -public final class space/kscience/kmath/operations/ExtendedFieldOperations$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun minus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun pow (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun sqrt (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object; - public static fun tan (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object; - public static fun tanh (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/operations/ExtendedFieldOperations;Ljava/lang/Object;)Ljava/lang/Object; + public fun tan (Ljava/lang/Object;)Ljava/lang/Object; + public fun tanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } public abstract interface class space/kscience/kmath/operations/Field : space/kscience/kmath/operations/FieldOperations, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring, space/kscience/kmath/operations/ScaleOperations { - public abstract fun number (Ljava/lang/Number;)Ljava/lang/Object; -} - -public final class space/kscience/kmath/operations/Field$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun minus (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun number (Lspace/kscience/kmath/operations/Field;Ljava/lang/Number;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun times (Lspace/kscience/kmath/operations/Field;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Field;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Ljava/lang/Object; } public abstract interface class space/kscience/kmath/operations/FieldOperations : space/kscience/kmath/operations/RingOperations { public static final field Companion Lspace/kscience/kmath/operations/FieldOperations$Companion; public static final field DIV_OPERATION Ljava/lang/String; - public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public abstract fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; } @@ -1885,20 +1238,6 @@ public final class space/kscience/kmath/operations/FieldOperations$Companion { public static final field DIV_OPERATION Ljava/lang/String; } -public final class space/kscience/kmath/operations/FieldOperations$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun minus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/operations/FieldOperations;Ljava/lang/Object;)Ljava/lang/Object; -} - public final class space/kscience/kmath/operations/FloatField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/Norm { public static final field INSTANCE Lspace/kscience/kmath/operations/FloatField; public fun acos (F)Ljava/lang/Float; @@ -1915,20 +1254,12 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; public fun atanh (F)Ljava/lang/Float; public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;FF)Ljava/lang/Float; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Float; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Float; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun cos (F)Ljava/lang/Float; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cosh (F)Ljava/lang/Float; public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun div (FF)Ljava/lang/Float; - public fun div (FLjava/lang/Number;)Ljava/lang/Float; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (FF)Ljava/lang/Float; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -1938,9 +1269,6 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Float; public synthetic fun getZero ()Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;F)Ljava/lang/Float; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun ln (F)Ljava/lang/Float; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; public fun minus (FF)Ljava/lang/Float; @@ -1953,67 +1281,39 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun plus (FF)Ljava/lang/Float; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun pow (FLjava/lang/Number;)Ljava/lang/Float; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power (FLjava/lang/Number;)Ljava/lang/Float; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;FLjava/lang/Number;)Ljava/lang/Float; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun scale (FD)Ljava/lang/Float; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun sin (F)Ljava/lang/Float; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh (F)Ljava/lang/Float; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (F)Ljava/lang/Float; - public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; public fun tan (F)Ljava/lang/Float; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; public fun tanh (F)Ljava/lang/Float; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; public fun times (FF)Ljava/lang/Float; - public fun times (FLjava/lang/Number;)Ljava/lang/Float; - public fun times (Ljava/lang/Number;F)Ljava/lang/Float; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (F)Ljava/lang/Float; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;F)Ljava/lang/Float; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public fun unaryPlus (F)Ljava/lang/Float; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; } public abstract interface class space/kscience/kmath/operations/Group : space/kscience/kmath/operations/GroupOperations { public abstract fun getZero ()Ljava/lang/Object; } -public final class space/kscience/kmath/operations/Group$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Ljava/lang/Object; - public static fun minus (Lspace/kscience/kmath/operations/Group;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/Group;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Group;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/operations/Group;Ljava/lang/Object;)Ljava/lang/Object; -} - public abstract interface class space/kscience/kmath/operations/GroupOperations : space/kscience/kmath/operations/Algebra { public static final field Companion Lspace/kscience/kmath/operations/GroupOperations$Companion; public static final field MINUS_OPERATION Ljava/lang/String; public static final field PLUS_OPERATION Ljava/lang/String; public abstract fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public abstract fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public abstract fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; } public final class space/kscience/kmath/operations/GroupOperations$Companion { @@ -2021,36 +1321,14 @@ public final class space/kscience/kmath/operations/GroupOperations$Companion { public static final field PLUS_OPERATION Ljava/lang/String; } -public final class space/kscience/kmath/operations/GroupOperations$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun minus (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/operations/GroupOperations;Ljava/lang/Object;)Ljava/lang/Object; -} - public final class space/kscience/kmath/operations/IntRing : space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring { public static final field INSTANCE Lspace/kscience/kmath/operations/IntRing; public fun add (II)Ljava/lang/Integer; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;II)Ljava/lang/Integer; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Integer; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Integer; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun getOne ()Ljava/lang/Integer; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Integer; public synthetic fun getZero ()Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;I)Ljava/lang/Integer; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun minus (II)Ljava/lang/Integer; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (II)Ljava/lang/Integer; @@ -2061,18 +1339,10 @@ public final class space/kscience/kmath/operations/IntRing : space/kscience/kmat public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun plus (II)Ljava/lang/Integer; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;ILjava/lang/Number;)Ljava/lang/Integer; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun times (II)Ljava/lang/Integer; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (I)Ljava/lang/Integer; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;I)Ljava/lang/Integer; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public fun unaryPlus (I)Ljava/lang/Integer; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; } public final class space/kscience/kmath/operations/JBigDecimalField : space/kscience/kmath/operations/JBigDecimalFieldBase { @@ -2089,98 +1359,44 @@ public abstract class space/kscience/kmath/operations/JBigDecimalFieldBase : spa public fun ()V public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Ljava/math/BigDecimal; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/math/BigDecimal; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Ljava/math/BigDecimal;Ljava/lang/Number;)Ljava/math/BigDecimal; - public fun div (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Ljava/math/BigDecimal; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Ljava/math/BigDecimal; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Ljava/math/BigDecimal; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Ljava/math/BigDecimal;Ljava/lang/Number;)Ljava/math/BigDecimal; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power (Ljava/math/BigDecimal;Ljava/lang/Number;)Ljava/math/BigDecimal; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Ljava/math/BigDecimal;Ljava/lang/Number;)Ljava/math/BigDecimal; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Ljava/math/BigDecimal;D)Ljava/math/BigDecimal; public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; public fun sqrt (Ljava/math/BigDecimal;)Ljava/math/BigDecimal; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/math/BigDecimal;Ljava/lang/Number;)Ljava/math/BigDecimal; - public fun times (Ljava/math/BigDecimal;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Ljava/math/BigDecimal;)Ljava/math/BigDecimal; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Ljava/math/BigDecimal;)Ljava/math/BigDecimal; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Ljava/math/BigDecimal;)Ljava/math/BigDecimal; } public final class space/kscience/kmath/operations/JBigIntegerField : space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring { public static final field INSTANCE Lspace/kscience/kmath/operations/JBigIntegerField; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Ljava/math/BigInteger; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/math/BigInteger; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Ljava/math/BigInteger; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Ljava/math/BigInteger; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/math/BigInteger;)Ljava/math/BigInteger; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Ljava/math/BigInteger; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Ljava/math/BigInteger;Ljava/lang/Number;)Ljava/math/BigInteger; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Ljava/math/BigInteger;)Ljava/math/BigInteger; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Ljava/math/BigInteger;)Ljava/math/BigInteger; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Ljava/math/BigInteger;)Ljava/math/BigInteger; } public abstract interface annotation class space/kscience/kmath/operations/KMathContext : java/lang/annotation/Annotation { @@ -2190,20 +1406,10 @@ public final class space/kscience/kmath/operations/LongRing : space/kscience/kma public static final field INSTANCE Lspace/kscience/kmath/operations/LongRing; public fun add (JJ)Ljava/lang/Long; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;JJ)Ljava/lang/Long; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Long; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Long; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; public fun getOne ()Ljava/lang/Long; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Long; public synthetic fun getZero ()Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;J)Ljava/lang/Long; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun minus (JJ)Ljava/lang/Long; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply (JJ)Ljava/lang/Long; @@ -2214,64 +1420,23 @@ public final class space/kscience/kmath/operations/LongRing : space/kscience/kma public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun plus (JJ)Ljava/lang/Long; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;JLjava/lang/Number;)Ljava/lang/Long; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun times (JJ)Ljava/lang/Long; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (J)Ljava/lang/Long; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;J)Ljava/lang/Long; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public fun unaryPlus (J)Ljava/lang/Long; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; } public abstract interface class space/kscience/kmath/operations/Norm { public abstract fun norm (Ljava/lang/Object;)Ljava/lang/Object; } -public final class space/kscience/kmath/operations/NumbersAddOperations$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun minus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun minus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun minus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun unaryOperation (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/operations/NumbersAddOperations;Ljava/lang/Object;)Ljava/lang/Object; -} - public abstract interface class space/kscience/kmath/operations/NumericAlgebra : space/kscience/kmath/operations/Algebra { - public abstract fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public abstract fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public abstract fun number (Ljava/lang/Number;)Ljava/lang/Object; - public abstract fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public abstract fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; -} - -public final class space/kscience/kmath/operations/NumericAlgebra$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;)Ljava/lang/Object; - public static fun leftSideNumberOperation (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun leftSideNumberOperationFunction (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun rightSideNumberOperation (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun rightSideNumberOperationFunction (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun unaryOperation (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/NumericAlgebra;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; } public final class space/kscience/kmath/operations/NumericAlgebraKt { @@ -2286,9 +1451,9 @@ public abstract interface class space/kscience/kmath/operations/PowerOperations public static final field Companion Lspace/kscience/kmath/operations/PowerOperations$Companion; public static final field POW_OPERATION Ljava/lang/String; public static final field SQRT_OPERATION Ljava/lang/String; - public abstract fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public abstract fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public abstract fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; + public fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; } public final class space/kscience/kmath/operations/PowerOperations$Companion { @@ -2296,96 +1461,37 @@ public final class space/kscience/kmath/operations/PowerOperations$Companion { public static final field SQRT_OPERATION Ljava/lang/String; } -public final class space/kscience/kmath/operations/PowerOperations$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun pow (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun sqrt (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/PowerOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; -} - public abstract interface class space/kscience/kmath/operations/Ring : space/kscience/kmath/operations/Group, space/kscience/kmath/operations/RingOperations { public abstract fun getOne ()Ljava/lang/Object; } -public final class space/kscience/kmath/operations/Ring$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Ljava/lang/Object; - public static fun minus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/Ring;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;)Ljava/lang/Object; -} - public abstract interface class space/kscience/kmath/operations/RingOperations : space/kscience/kmath/operations/GroupOperations { public static final field Companion Lspace/kscience/kmath/operations/RingOperations$Companion; public static final field TIMES_OPERATION Ljava/lang/String; - public abstract fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public abstract fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; } public final class space/kscience/kmath/operations/RingOperations$Companion { public static final field TIMES_OPERATION Ljava/lang/String; } -public final class space/kscience/kmath/operations/RingOperations$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun minus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public static fun unaryPlus (Lspace/kscience/kmath/operations/RingOperations;Ljava/lang/Object;)Ljava/lang/Object; -} - public abstract interface class space/kscience/kmath/operations/ScaleOperations : space/kscience/kmath/operations/Algebra { - public abstract fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public abstract fun scale (Ljava/lang/Object;D)Ljava/lang/Object; - public abstract fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; -} - -public final class space/kscience/kmath/operations/ScaleOperations$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun div (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/ScaleOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; } public final class space/kscience/kmath/operations/ShortRing : space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring { public static final field INSTANCE Lspace/kscience/kmath/operations/ShortRing; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (SS)Ljava/lang/Short; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;SS)Ljava/lang/Short; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Short; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Short; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Ljava/lang/Short; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Short; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;S)Ljava/lang/Short; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus (SS)Ljava/lang/Short; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -2396,18 +1502,10 @@ public final class space/kscience/kmath/operations/ShortRing : space/kscience/km public fun number (Ljava/lang/Number;)Ljava/lang/Short; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun plus (SS)Ljava/lang/Short; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;SLjava/lang/Number;)Ljava/lang/Short; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun times (SS)Ljava/lang/Short; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (S)Ljava/lang/Short; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;S)Ljava/lang/Short; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (S)Ljava/lang/Short; } public abstract interface class space/kscience/kmath/operations/TrigonometricOperations : space/kscience/kmath/operations/Algebra { @@ -2435,15 +1533,6 @@ public final class space/kscience/kmath/operations/TrigonometricOperations$Compa public static final field TAN_OPERATION Ljava/lang/String; } -public final class space/kscience/kmath/operations/TrigonometricOperations$DefaultImpls { - public static fun binaryOperation (Lspace/kscience/kmath/operations/TrigonometricOperations;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun binaryOperationFunction (Lspace/kscience/kmath/operations/TrigonometricOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public static fun bindSymbol (Lspace/kscience/kmath/operations/TrigonometricOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun bindSymbolOrNull (Lspace/kscience/kmath/operations/TrigonometricOperations;Ljava/lang/String;)Ljava/lang/Object; - public static fun unaryOperation (Lspace/kscience/kmath/operations/TrigonometricOperations;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public static fun unaryOperationFunction (Lspace/kscience/kmath/operations/TrigonometricOperations;Ljava/lang/String;)Lkotlin/jvm/functions/Function1; -} - public final class space/kscience/kmath/structures/ArrayBuffer : space/kscience/kmath/structures/MutableBuffer { public fun ([Ljava/lang/Object;)V public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; @@ -2467,7 +1556,7 @@ public final class space/kscience/kmath/structures/Buffer$Companion { } public final class space/kscience/kmath/structures/BufferKt { - public static final fun asBuffer (Ljava/util/List;)Ljava/util/List; + public static final fun asBuffer (Ljava/util/List;)Lspace/kscience/kmath/structures/ListBuffer; public static final fun asBuffer ([Ljava/lang/Object;)Lspace/kscience/kmath/structures/ArrayBuffer; public static final fun asMutableBuffer (Ljava/util/List;)Ljava/util/List; public static final fun asReadOnly (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; @@ -2478,6 +1567,7 @@ public final class space/kscience/kmath/structures/BufferOperationKt { public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable; public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence; public static final fun fold (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; + public static final fun map (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; public static final fun toList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List; } @@ -2525,21 +1615,10 @@ public final class space/kscience/kmath/structures/DoubleBufferField : space/ksc public fun atan-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; public fun atanh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cos-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun cosh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public fun div (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; @@ -2549,51 +1628,26 @@ public final class space/kscience/kmath/structures/DoubleBufferField : space/ksc public final fun getSize ()I public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/structures/Buffer; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; public fun ln-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;D)[D public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sin-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; public fun tan-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; public fun tanh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public fun times (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; } public final class space/kscience/kmath/structures/DoubleBufferFieldOperations : space/kscience/kmath/operations/ExtendedFieldOperations { @@ -2612,54 +1666,30 @@ public final class space/kscience/kmath/structures/DoubleBufferFieldOperations : public fun atan-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; public fun atanh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cos-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun cosh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun div (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; public fun exp-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; public fun ln-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun multiply-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sin-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; public fun tan-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; public fun tanh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; } public final class space/kscience/kmath/structures/DoubleBufferKt { @@ -2761,23 +1791,11 @@ public final class space/kscience/kmath/structures/IntBufferKt { } public final class space/kscience/kmath/structures/ListBuffer : space/kscience/kmath/structures/Buffer { - public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/ListBuffer; - public static fun constructor-impl (Ljava/util/List;)Ljava/util/List; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Ljava/util/List;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Ljava/util/List;Ljava/util/List;)Z + public fun (Ljava/util/List;)V public fun get (I)Ljava/lang/Object; - public static fun get-impl (Ljava/util/List;I)Ljava/lang/Object; public final fun getList ()Ljava/util/List; public fun getSize ()I - public static fun getSize-impl (Ljava/util/List;)I - public fun hashCode ()I - public static fun hashCode-impl (Ljava/util/List;)I public fun iterator ()Ljava/util/Iterator; - public static fun iterator-impl (Ljava/util/List;)Ljava/util/Iterator; - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Ljava/util/List;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Ljava/util/List; } public final class space/kscience/kmath/structures/LongBuffer : space/kscience/kmath/structures/MutableBuffer { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt index 6f737bd38..2c88bb021 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt @@ -4,7 +4,7 @@ import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI @UnstableKMathAPI -public inline class UnivariateDomain(public val range: ClosedFloatingPointRange) : DoubleDomain { +public class UnivariateDomain(public val range: ClosedFloatingPointRange) : DoubleDomain { public override val dimension: Int get() = 1 public operator fun contains(d: Double): Boolean = range.contains(d) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index 9fb8f28c8..ee66892be 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -44,7 +44,7 @@ public abstract class FunctionalExpressionAlgebra>( } /** - * A context class for [Expression] construction for [Group] algebras. + * A context class for [Expression] construction for [Ring] algebras. */ public open class FunctionalExpressionGroup>( algebra: A, @@ -168,7 +168,7 @@ public open class FunctionalExpressionExtendedField>( public override fun bindSymbol(value: String): Expression = super.bindSymbol(value) } -public inline fun > A.expressionInSpace(block: FunctionalExpressionGroup.() -> Expression): Expression = +public inline fun > A.expressionInSpace(block: FunctionalExpressionGroup.() -> Expression): Expression = FunctionalExpressionGroup(this).block() public inline fun > A.expressionInRing(block: FunctionalExpressionRing.() -> Expression): Expression = diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt index 3151ebaa0..2a9d71e99 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt @@ -19,7 +19,7 @@ public object MstAlgebra : NumericAlgebra { } /** - * [Group] over [MST] nodes. + * [Ring] over [MST] nodes. */ public object MstGroup : Group, NumericAlgebra, ScaleOperations { public override val zero: MST.Numeric = number(0.0) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt index 4db4b5828..071f0ffbc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt @@ -5,6 +5,7 @@ import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.structures.BufferFactory +import kotlin.jvm.JvmInline /** * An environment to easy transform indexed variables to symbols and back. @@ -53,7 +54,8 @@ public interface SymbolIndexer { } @UnstableKMathAPI -public inline class SimpleSymbolIndexer(override val symbols: List) : SymbolIndexer +@JvmInline +public value class SimpleSymbolIndexer(override val symbols: List) : SymbolIndexer /** * Execute the block with symbol indexer based on given symbol order diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt index fbf080032..d18ff3798 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt @@ -2,16 +2,15 @@ package space.kscience.kmath.expressions import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.Ring import kotlin.contracts.InvocationKind import kotlin.contracts.contract /** - * Creates a functional expression with this [Group]. + * Creates a functional expression with this [Ring]. */ -public inline fun Group.spaceExpression(block: FunctionalExpressionGroup>.() -> Expression): Expression { +public inline fun Ring.spaceExpression(block: FunctionalExpressionGroup>.() -> Expression): Expression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return FunctionalExpressionGroup(this).block() } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt index 2c9774b6a..2a739b104 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.misc +import kotlin.jvm.JvmInline import kotlin.properties.ReadOnlyProperty /** @@ -21,7 +22,8 @@ public interface Symbol { /** * A [Symbol] with a [String] identity */ -public inline class StringSymbol(override val identity: String) : Symbol { +@JvmInline +public value class StringSymbol(override val identity: String) : Symbol { override fun toString(): String = identity } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt index 6466695a6..a38214474 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.misc -import space.kscience.kmath.operations.Group +import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.invoke import kotlin.jvm.JvmName @@ -37,7 +37,7 @@ public fun List.cumulative(initial: R, operation: (R, T) -> R): List Iterable.cumulativeSum(group: Group): Iterable = +public fun Iterable.cumulativeSum(group: Ring): Iterable = group { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") @@ -49,7 +49,7 @@ public fun Iterable.cumulativeSum(): Iterable = cumulative(0) { elemen @JvmName("cumulativeSumOfLong") public fun Iterable.cumulativeSum(): Iterable = cumulative(0L) { element, sum -> sum + element } -public fun Sequence.cumulativeSum(group: Group): Sequence = +public fun Sequence.cumulativeSum(group: Ring): Sequence = group { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") @@ -61,7 +61,7 @@ public fun Sequence.cumulativeSum(): Sequence = cumulative(0) { elemen @JvmName("cumulativeSumOfLong") public fun Sequence.cumulativeSum(): Sequence = cumulative(0L) { element, sum -> sum + element } -public fun List.cumulativeSum(group: Group): List = +public fun List.cumulativeSum(group: Ring): List = group { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt index 67e94df74..b8470c59a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt @@ -80,13 +80,13 @@ public open class BufferedFieldND>( } // group factories -public fun > AlgebraND.Companion.group( +public fun > AlgebraND.Companion.group( space: A, bufferFactory: BufferFactory, vararg shape: Int, ): BufferedGroupND = BufferedGroupND(shape, space, bufferFactory) -public inline fun , R> A.ndGroup( +public inline fun , R> A.ndGroup( noinline bufferFactory: BufferFactory, vararg shape: Int, action: BufferedGroupND.() -> R, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 5483ed28f..4eaf763c9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -2,6 +2,7 @@ package space.kscience.kmath.nd import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asSequence +import kotlin.jvm.JvmInline /** * A structure that is guaranteed to be one-dimensional @@ -22,7 +23,8 @@ public interface Structure1D : StructureND, Buffer { /** * A 1D wrapper for nd-structure */ -private inline class Structure1DWrapper(val structure: StructureND) : Structure1D { +@JvmInline +private value class Structure1DWrapper(val structure: StructureND) : Structure1D { override val shape: IntArray get() = structure.shape override val size: Int get() = structure.shape[0] @@ -34,7 +36,8 @@ private inline class Structure1DWrapper(val structure: StructureND) : Stru /** * A structure wrapper for buffer */ -private inline class Buffer1DWrapper(val buffer: Buffer) : Structure1D { +@JvmInline +private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D { override val shape: IntArray get() = intArrayOf(buffer.size) override val size: Int get() = buffer.size diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 5dfdd028a..c476088e2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -3,6 +3,7 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.VirtualBuffer +import kotlin.jvm.JvmInline import kotlin.reflect.KClass /** @@ -60,7 +61,8 @@ public interface Structure2D : StructureND { /** * A 2D wrapper for nd-structure */ -private inline class Structure2DWrapper(val structure: StructureND) : Structure2D { +@JvmInline +private value class Structure2DWrapper(val structure: StructureND) : Structure2D { override val shape: IntArray get() = structure.shape override val rowNum: Int get() = shape[0] diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt index c0380a197..7e815c9af 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt @@ -50,7 +50,7 @@ public operator fun , S : NumbersAddOperations> T.mi * @param b the addend. * @return the sum. */ -public operator fun , S : Group> T.plus(b: T): T = +public operator fun , S : Ring> T.plus(b: T): T = context.add(this, b) ///** @@ -88,7 +88,7 @@ public operator fun , F : Field> T.div(b: T): T = * @param S the type of space. */ @UnstableKMathAPI -public interface SpaceElement, S : Group> : AlgebraElement +public interface GroupElement, S : Group> : AlgebraElement /** * The element of [Ring]. @@ -98,7 +98,7 @@ public interface SpaceElement, S : Group> : AlgebraEle * @param R the type of ring. */ @UnstableKMathAPI -public interface RingElement, R : Ring> : SpaceElement +public interface RingElement, R : Ring> : GroupElement /** * The element of [Field]. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 817bc9f9c..a83a7bc24 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -440,7 +440,7 @@ public fun String.parseBigInteger(): BigInt? { var res = BigInt.ZERO var digitValue = BigInt.ONE - val sPositiveUpper = sPositive.toUpperCase() + val sPositiveUpper = sPositive.uppercase() if (sPositiveUpper.startsWith("0X")) { // hex representation val sHex = sPositiveUpper.substring(2) @@ -456,7 +456,7 @@ public fun String.parseBigInteger(): BigInt? { if (ch !in '0'..'9') { return null } - res += digitValue * (ch.toInt() - '0'.toInt()) + res += digitValue * (ch.code - '0'.code) digitValue *= 10.toBigInt() } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt index 84d4f8064..79d47fe91 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt @@ -147,7 +147,7 @@ public interface ScaleOperations : Algebra { * TODO to be removed and replaced by extensions after multiple receivers are there */ @UnstableKMathAPI -public interface NumbersAddOperations : Group, NumericAlgebra { +public interface NumbersAddOperations : Ring, NumericAlgebra { /** * Addition of element and scalar. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 93ce92f37..bf984fc1c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -1,53 +1,53 @@ package space.kscience.kmath.operations /** - * Returns the sum of all elements in the iterable in this [Group]. + * Returns the sum of all elements in the iterable in this [Ring]. * * @receiver the algebra that provides addition. * @param data the iterable to sum up. * @return the sum. */ -public fun Group.sum(data: Iterable): T = data.fold(zero) { left, right -> +public fun Ring.sum(data: Iterable): T = data.fold(zero) { left, right -> add(left, right) } /** - * Returns the sum of all elements in the sequence in this [Group]. + * Returns the sum of all elements in the sequence in this [Ring]. * * @receiver the algebra that provides addition. * @param data the sequence to sum up. * @return the sum. */ -public fun Group.sum(data: Sequence): T = data.fold(zero) { left, right -> +public fun Ring.sum(data: Sequence): T = data.fold(zero) { left, right -> add(left, right) } /** - * Returns an average value of elements in the iterable in this [Group]. + * Returns an average value of elements in the iterable in this [Ring]. * * @receiver the algebra that provides addition and division. * @param data the iterable to find average. * @return the average value. * @author Iaroslav Postovalov */ -public fun S.average(data: Iterable): T where S : Group, S : ScaleOperations = +public fun S.average(data: Iterable): T where S : Ring, S : ScaleOperations = sum(data) / data.count() /** - * Returns an average value of elements in the sequence in this [Group]. + * Returns an average value of elements in the sequence in this [Ring]. * * @receiver the algebra that provides addition and division. * @param data the sequence to find average. * @return the average value. * @author Iaroslav Postovalov */ -public fun S.average(data: Sequence): T where S : Group, S : ScaleOperations = +public fun S.average(data: Sequence): T where S : Ring, S : ScaleOperations = sum(data) / data.count() /** * Absolute of the comparable [value] */ -public fun > Group.abs(value: T): T = if (value > zero) value else -value +public fun > Ring.abs(value: T): T = if (value > zero) value else -value /** * Returns the sum of all elements in the iterable in provided space. @@ -56,7 +56,7 @@ public fun > Group.abs(value: T): T = if (value > zero) val * @param group the algebra that provides addition. * @return the sum. */ -public fun Iterable.sumWith(group: Group): T = group.sum(this) +public fun Iterable.sumWith(group: Ring): T = group.sum(this) /** * Returns the sum of all elements in the sequence in provided space. @@ -65,28 +65,28 @@ public fun Iterable.sumWith(group: Group): T = group.sum(this) * @param group the algebra that provides addition. * @return the sum. */ -public fun Sequence.sumWith(group: Group): T = group.sum(this) +public fun Sequence.sumWith(group: Ring): T = group.sum(this) /** - * Returns an average value of elements in the iterable in this [Group]. + * Returns an average value of elements in the iterable in this [Ring]. * * @receiver the iterable to find average. * @param space the algebra that provides addition and division. * @return the average value. * @author Iaroslav Postovalov */ -public fun Iterable.averageWith(space: S): T where S : Group, S : ScaleOperations = +public fun Iterable.averageWith(space: S): T where S : Ring, S : ScaleOperations = space.average(this) /** - * Returns an average value of elements in the sequence in this [Group]. + * Returns an average value of elements in the sequence in this [Ring]. * * @receiver the sequence to find average. * @param space the algebra that provides addition and division. * @return the average value. * @author Iaroslav Postovalov */ -public fun Sequence.averageWith(space: S): T where S : Group, S : ScaleOperations = +public fun Sequence.averageWith(space: S): T where S : Ring, S : ScaleOperations = space.average(this) //TODO optimized power operation diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 168a92c37..6882d7b2a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.structures +import kotlin.jvm.JvmInline import kotlin.reflect.KClass /** @@ -43,7 +44,7 @@ public interface Buffer { /** * Check the element-by-element match of content of two buffers. */ - public fun contentEquals(first: Buffer, second: Buffer): Boolean{ + public fun contentEquals(first: Buffer, second: Buffer): Boolean { if (first.size != second.size) return false for (i in first.indices) { if (first[i] != second[i]) return false @@ -187,9 +188,8 @@ public interface MutableBuffer : Buffer { * @param T the type of elements contained in the buffer. * @property list The underlying list. */ -public inline class ListBuffer(public val list: List) : Buffer { - override val size: Int - get() = list.size +public class ListBuffer(public val list: List) : Buffer { + override val size: Int get() = list.size override operator fun get(index: Int): T = list[index] override operator fun iterator(): Iterator = list.iterator() @@ -206,7 +206,8 @@ public fun List.asBuffer(): ListBuffer = ListBuffer(this) * @param T the type of elements contained in the buffer. * @property list The underlying list. */ -public inline class MutableListBuffer(public val list: MutableList) : MutableBuffer { +@JvmInline +public value class MutableListBuffer(public val list: MutableList) : MutableBuffer { override val size: Int get() = list.size @@ -257,7 +258,8 @@ public fun Array.asBuffer(): ArrayBuffer = ArrayBuffer(this) * @param T the type of elements contained in the buffer. * @property buffer The underlying buffer. */ -public inline class ReadOnlyBuffer(public val buffer: MutableBuffer) : Buffer { +@JvmInline +public value class ReadOnlyBuffer(public val buffer: MutableBuffer) : Buffer { override val size: Int get() = buffer.size override operator fun get(index: Int): T = buffer[index] diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt index 0a23d31fe..912f4b070 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt @@ -1,12 +1,14 @@ package space.kscience.kmath.structures +import kotlin.jvm.JvmInline + /** * Specialized [MutableBuffer] implementation over [DoubleArray]. * * @property array the underlying array. */ -@Suppress("OVERRIDE_BY_INLINE") -public inline class DoubleBuffer(public val array: DoubleArray) : MutableBuffer { +@JvmInline +public value class DoubleBuffer(public val array: DoubleArray) : MutableBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Double = array[index] diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt index 5c4ec3b05..8063c3a7f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt @@ -1,12 +1,15 @@ package space.kscience.kmath.structures +import kotlin.jvm.JvmInline + /** * Specialized [MutableBuffer] implementation over [FloatArray]. * * @property array the underlying array. * @author Iaroslav Postovalov */ -public inline class FloatBuffer(public val array: FloatArray) : MutableBuffer { +@JvmInline +public value class FloatBuffer(public val array: FloatArray) : MutableBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Float = array[index] diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt index 32dfcf9aa..649326a7a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt @@ -1,11 +1,14 @@ package space.kscience.kmath.structures +import kotlin.jvm.JvmInline + /** * Specialized [MutableBuffer] implementation over [IntArray]. * * @property array the underlying array. */ -public inline class IntBuffer(public val array: IntArray) : MutableBuffer { +@JvmInline +public value class IntBuffer(public val array: IntArray) : MutableBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Int = array[index] diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt index 48b1d7a7b..b41d45c88 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt @@ -1,11 +1,14 @@ package space.kscience.kmath.structures +import kotlin.jvm.JvmInline + /** * Specialized [MutableBuffer] implementation over [LongArray]. * * @property array the underlying array. */ -public inline class LongBuffer(public val array: LongArray) : MutableBuffer { +@JvmInline +public value class LongBuffer(public val array: LongArray) : MutableBuffer { override val size: Int get() = array.size override operator fun get(index: Int): Long = array[index] diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt index 7832bb863..9a5775f6d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt @@ -1,11 +1,14 @@ package space.kscience.kmath.structures +import kotlin.jvm.JvmInline + /** * Specialized [MutableBuffer] implementation over [ShortArray]. * * @property array the underlying array. */ -public inline class ShortBuffer(public val array: ShortArray) : MutableBuffer { +@JvmInline +public value class ShortBuffer(public val array: ShortArray) : MutableBuffer { public override val size: Int get() = array.size public override operator fun get(index: Int): Short = array[index] diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt index 5f8bbe21f..9d0e19dbc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt @@ -53,12 +53,18 @@ public fun Buffer.toMutableList(): MutableList = when (this) { public inline fun Buffer.toTypedArray(): Array = Array(size, ::get) /** - * Create a new buffer from this one with the given mapping function. - * Provided [BufferFactory] is used to construct the new buffer. + * Create a new buffer from this one with the given mapping function and using [Buffer.Companion.auto] buffer factory. */ -public inline fun Buffer.map( - bufferFactory: BufferFactory = Buffer.Companion::auto, - crossinline block: (T) -> R, +public inline fun Buffer.map(block: (T) -> R): Buffer = + Buffer.auto(size) { block(get(it)) } + +/** + * Create a new buffer from this one with the given mapping function. + * Provided [bufferFactory] is used to construct the new buffer. + */ +public fun Buffer.map( + bufferFactory: BufferFactory, + block: (T) -> R, ): Buffer = bufferFactory(size) { block(get(it)) } /** diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt index a9cd4454c..d533ed83e 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.testutils -import space.kscience.kmath.operations.Group +import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import kotlin.test.assertEquals @@ -12,7 +12,7 @@ internal open class SpaceVerifier( val b: T, val c: T, val x: Number, -) : AlgebraicVerifier> where S : Group, S : ScaleOperations { +) : AlgebraicVerifier> where S : Ring, S : ScaleOperations { override fun verify() { algebra { assertEquals(a + b + c, a + (b + c), "Addition in $algebra is not associative.") diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt index 7d4914a01..dd2d475c4 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt @@ -5,8 +5,8 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.runningReduce import kotlinx.coroutines.flow.scan -import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.GroupOperations +import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke @@ -14,7 +14,7 @@ public fun Flow.cumulativeSum(group: GroupOperations): Flow = group { runningReduce { sum, element -> sum + element } } @ExperimentalCoroutinesApi -public fun Flow.mean(space: S): Flow where S : Group, S : ScaleOperations = space { +public fun Flow.mean(space: S): Flow where S : Ring, S : ScaleOperations = space { data class Accumulator(var sum: T, var num: Int) scan(Accumulator(zero, 0)) { sum, element -> diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt index dd85a97cb..fa477501d 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt @@ -7,6 +7,7 @@ import space.kscience.kmath.linear.transpose import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Ring +import kotlin.jvm.JvmInline /** * A matrix with compile-time controlled dimension @@ -39,7 +40,8 @@ public interface DMatrix : Structure2D { /** * An inline wrapper for a Matrix */ -public inline class DMatrixWrapper( +@JvmInline +public value class DMatrixWrapper( private val structure: Structure2D, ) : DMatrix { override val shape: IntArray get() = structure.shape @@ -68,7 +70,8 @@ public interface DPoint : Point { /** * Dimension-safe point wrapper */ -public inline class DPointWrapper(public val point: Point) : +@JvmInline +public value class DPointWrapper(public val point: Point) : DPoint { override val size: Int get() = point.size @@ -81,7 +84,8 @@ public inline class DPointWrapper(public val point: Point) /** * Basic operations on dimension-safe matrices. Operates on [Matrix] */ -public inline class DMatrixContext>(public val context: LinearSpace) { +@JvmInline +public value class DMatrixContext>(public val context: LinearSpace) { public inline fun Matrix.coerce(): DMatrix { require(rowNum == Dimension.dim().toInt()) { "Row number mismatch: expected ${Dimension.dim()} but found $rowNum" diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 550785812..d3f0275ce 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -14,7 +14,7 @@ import kotlin.math.pow * * @param coefficients constant is the leftmost coefficient. */ -public inline class Polynomial(public val coefficients: List) +public class Polynomial(public val coefficients: List) /** * Returns a [Polynomial] instance with given [coefficients]. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt new file mode 100644 index 000000000..d58b6131f --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2015 Alexander Nozik. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package space.kscience.kmath.integration + +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.indices + +/** + * A simple one-pass integrator based on Gauss rule + */ +public class GaussIntegrator internal constructor( + public val algebra: Ring, + private val points: Buffer, + private val weights: Buffer, +) : UnivariateIntegrator { + + init { + require(points.size == weights.size) { "Inconsistent points and weights sizes" } + } + + override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand = with(algebra) { + val f = integrand.function + var res = zero + var c = zero + for (i in points.indices) { + val x: T = points[i] + val w: T = weights[i] + val y: T = w * f(x) - c + val t = res + y + c = t - res - y + res = t + } + return integrand + IntegrandValue(res) + IntegrandCalls(integrand.calls + points.size) + } + + public companion object { + + public fun integrate( + range: ClosedRange, + numPoints: Int = 100, + ruleFactory: GaussIntegratorRuleFactory = GaussLegendreDoubleRuleFactory, + function: (Double) -> Double, + ): Double { + val (points, weights) = ruleFactory.build(numPoints, range) + return GaussIntegrator(DoubleField, points, weights).integrate( + UnivariateIntegrand(function, IntegrationRange(range)) + ).value!! + } + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt new file mode 100644 index 000000000..234859991 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt @@ -0,0 +1,166 @@ +package space.kscience.kmath.integration + +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.structures.* +import kotlin.jvm.Synchronized +import kotlin.math.ulp +import kotlin.native.concurrent.ThreadLocal + +public interface GaussIntegratorRuleFactory { + public val algebra: Ring + public val bufferFactory: BufferFactory + public fun build(numPoints: Int): Pair, Buffer> + + public companion object { + public fun double(numPoints: Int, range: ClosedRange): Pair, Buffer> = + GaussLegendreDoubleRuleFactory.build(numPoints, range) + } +} + +/** + * Create an integration rule by scaling existing normalized rule + */ +public fun > GaussIntegratorRuleFactory.build( + numPoints: Int, + range: ClosedRange, +): Pair, Buffer> { + val normalized = build(numPoints) + val points = with(algebra) { + val length = range.endInclusive - range.start + normalized.first.map(bufferFactory) { + range.start + length * it + } + } + + return points to normalized.second +} + + +/** + * Gauss integrator rule based ont Legendre polynomials. All rules are normalized to + * + * The code is based on Apache Commons Math source code version 3.6.1 + * https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/analysis/integration/gauss/LegendreRuleFactory.html + */ +@ThreadLocal +public object GaussLegendreDoubleRuleFactory : GaussIntegratorRuleFactory { + + override val algebra: Ring get() = DoubleField + + override val bufferFactory: BufferFactory get() = ::DoubleBuffer + + private val cache = HashMap, Buffer>>() + + @Synchronized + private fun getOrBuildRule(numPoints: Int): Pair, Buffer> = + cache.getOrPut(numPoints) { buildRule(numPoints) } + + + private fun buildRule(numPoints: Int): Pair, Buffer> { + if (numPoints == 1) { + // Break recursion. + return Pair( + DoubleBuffer(0.0), + DoubleBuffer(0.0) + ) + } + + // Get previous rule. + // If it has not been computed yet it will trigger a recursive call + // to this method. + val previousPoints: Buffer = getOrBuildRule(numPoints - 1).first + + // Compute next rule. + val points = DoubleArray(numPoints) + val weights = DoubleArray(numPoints) + + // Find i-th root of P[n+1] by bracketing. + val iMax = numPoints / 2 + for (i in 0 until iMax) { + // Lower-bound of the interval. + var a: Double = if (i == 0) -1.0 else previousPoints[i - 1] + // Upper-bound of the interval. + var b: Double = if (iMax == 1) 1.0 else previousPoints[i] + // P[j-1](a) + var pma = 1.0 + // P[j](a) + var pa = a + // P[j-1](b) + var pmb = 1.0 + // P[j](b) + var pb = b + for (j in 1 until numPoints) { + val two_j_p_1 = 2 * j + 1 + val j_p_1 = j + 1 + // P[j+1](a) + val ppa = (two_j_p_1 * a * pa - j * pma) / j_p_1 + // P[j+1](b) + val ppb = (two_j_p_1 * b * pb - j * pmb) / j_p_1 + pma = pa + pa = ppa + pmb = pb + pb = ppb + } + // Now pa = P[n+1](a), and pma = P[n](a) (same holds for b). + // Middle of the interval. + var c = 0.5 * (a + b) + // P[j-1](c) + var pmc = 1.0 + // P[j](c) + var pc = c + var done = false + while (!done) { + done = b - a <= c.ulp + pmc = 1.0 + pc = c + for (j in 1 until numPoints) { + // P[j+1](c) + val ppc = ((2 * j + 1) * c * pc - j * pmc) / (j + 1) + pmc = pc + pc = ppc + } + // Now pc = P[n+1](c) and pmc = P[n](c). + if (!done) { + if (pa * pc <= 0) { + b = c + pmb = pmc + pb = pc + } else { + a = c + pma = pmc + pa = pc + } + c = 0.5 * (a + b) + } + } + val d = numPoints * (pmc - c * pc) + val w = 2 * (1 - c * c) / (d * d) + points[i] = c + weights[i] = w + val idx = numPoints - i - 1 + points[idx] = -c + weights[idx] = w + } + // If "numberOfPoints" is odd, 0 is a root. + // Note: as written, the test for oddness will work for negative + // integers too (although it is not necessary here), preventing + // a FindBugs warning. + if (numPoints % 2 != 0) { + var pmc = 1.0 + var j = 1 + while (j < numPoints) { + pmc = -j * pmc / (j + 1) + j += 2 + } + val d = numPoints * pmc + val w = 2 / (d * d) + points[iMax] = 0.0 + weights[iMax] = w + } + return Pair(points.asBuffer(), weights.asBuffer()) + } + + override fun build(numPoints: Int): Pair, Buffer> = getOrBuildRule(numPoints) +} + diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt index 54a1e032c..881d58018 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt @@ -2,13 +2,13 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.GroupElement import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.SpaceElement import space.kscience.kmath.operations.invoke import kotlin.math.sqrt @OptIn(UnstableKMathAPI::class) -public interface Vector2D : Point, Vector, SpaceElement { +public interface Vector2D : Point, Vector, GroupElement { public val x: Double public val y: Double public override val context: Euclidean2DSpace get() = Euclidean2DSpace diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt index ed110e383..924487a79 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt @@ -2,13 +2,13 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.GroupElement import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.SpaceElement import space.kscience.kmath.operations.invoke import kotlin.math.sqrt @OptIn(UnstableKMathAPI::class) -public interface Vector3D : Point, Vector, SpaceElement { +public interface Vector3D : Point, Vector, GroupElement { public val x: Double public val y: Double public val z: Double diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt index 764ff116c..00875b92e 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt @@ -3,7 +3,7 @@ package space.kscience.kmath.histogram import kotlinx.atomicfu.atomic import kotlinx.atomicfu.getAndUpdate import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.Group +import space.kscience.kmath.operations.Ring /** * Common representation for atomic counters @@ -37,7 +37,7 @@ public class LongCounter : Counter { override val value: Long get() = innerValue.value } -public class ObjectCounter(public val group: Group) : Counter { +public class ObjectCounter(public val group: Ring) : Counter { private val innerValue = atomic(group.zero) override fun add(delta: T) { diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt index f55080b09..a5c6ffdce 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt @@ -7,8 +7,8 @@ import space.kscience.kmath.nd.FieldND import space.kscience.kmath.nd.Strides import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.Group +import space.kscience.kmath.operations.GroupElement import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.SpaceElement import space.kscience.kmath.operations.invoke /** @@ -23,7 +23,7 @@ public data class DomainBin>( public class IndexedHistogram, V : Any>( override val context: IndexedHistogramSpace, public val values: StructureND, -) : Histogram>, SpaceElement, IndexedHistogramSpace> { +) : Histogram>, GroupElement, IndexedHistogramSpace> { override fun get(point: Point): Bin? { val index = context.getIndex(point) ?: return null diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt index b1b2a10c2..b18b53952 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt @@ -3,7 +3,7 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.UnivariateDomain import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Group -import space.kscience.kmath.operations.SpaceElement +import space.kscience.kmath.operations.GroupElement import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asSequence @@ -31,7 +31,7 @@ public class UnivariateBin( @OptIn(UnstableKMathAPI::class) public interface UnivariateHistogram : Histogram, - SpaceElement> { + GroupElement> { public operator fun get(value: Double): UnivariateBin? public override operator fun get(point: Buffer): UnivariateBin? = get(point[0]) diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index 8ea992bcb..7d9967506 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -75,7 +75,7 @@ public interface Nd4jArrayAlgebra> : AlgebraND { * @param T the type of the element contained in ND structure. * @param S the type of space of structure elements. */ -public interface Nd4JArrayGroup> : GroupND, Nd4jArrayAlgebra { +public interface Nd4JArrayGroup> : GroupND, Nd4jArrayAlgebra { public override val zero: Nd4jArrayStructure get() = Nd4j.zeros(*shape).wrap() diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt index 15593aed5..4e02b1b9d 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt @@ -11,7 +11,7 @@ import kotlin.math.* /** * Implements [UnivariateDistribution] for the normal (gaussian) distribution. */ -public inline class NormalDistribution(public val sampler: GaussianSampler) : UnivariateDistribution { +public class NormalDistribution(public val sampler: GaussianSampler) : UnivariateDistribution { public constructor( mean: Double, standardDeviation: Double, diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt index e13d5ff69..ccfa4777a 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt @@ -8,7 +8,7 @@ import space.kscience.kmath.structures.indices * Arithmetic mean */ public class Mean( - private val group: Group, + private val group: Ring, private val division: (sum: T, count: Int) -> T, ) : ComposableStatistic, T>, BlockingStatistic { diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api index 0e4eac77e..bcfb49e61 100644 --- a/kmath-viktor/api/kmath-viktor.api +++ b/kmath-viktor/api/kmath-viktor.api @@ -28,42 +28,17 @@ public final class space/kscience/kmath/viktor/ViktorFieldND : space/kscience/km public fun ([I)V public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; public fun acos-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun acosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun add (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun add-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; public fun asin-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun asinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; public fun atan-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun atanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public fun combine-WKhNzhk (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cos-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun cosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun div (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun div (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun div (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; - public fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun div (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public fun div (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun divide (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; public fun exp-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; @@ -74,78 +49,34 @@ public final class space/kscience/kmath/viktor/ViktorFieldND : space/kscience/km public fun getShape ()[I public synthetic fun getZero ()Ljava/lang/Object; public fun getZero-6kW2wQc ()Lorg/jetbrains/bio/viktor/F64Array; - public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun leftSideNumberOperation (Ljava/lang/String;Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun leftSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; public fun ln-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public fun map-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; public fun mapIndexed-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array; - public fun minus (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun minus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun minus (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; - public fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun minus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; public fun minus-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number-8UOKELU (Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; - public fun plus (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun plus (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; public fun plus-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;D)Lorg/jetbrains/bio/viktor/F64Array; public fun plus-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun pow (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun pow (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public fun produce-8UOKELU (Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun rightSideNumberOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun rightSideNumberOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; - public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;D)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; public fun sin-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun sinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; public fun tan-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; - public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun tanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun times (DLspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun times (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun times (Ljava/lang/Number;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public synthetic fun times (Ljava/lang/Object;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun times (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public fun times (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun times-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public synthetic fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public synthetic fun unaryPlus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryPlus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } public final class space/kscience/kmath/viktor/ViktorStructureND : space/kscience/kmath/nd/MutableStructureND { @@ -159,8 +90,6 @@ public final class space/kscience/kmath/viktor/ViktorStructureND : space/kscienc public fun get ([I)Ljava/lang/Double; public synthetic fun get ([I)Ljava/lang/Object; public static fun get-impl (Lorg/jetbrains/bio/viktor/F64Array;[I)Ljava/lang/Double; - public fun getDimension ()I - public static fun getDimension-impl (Lorg/jetbrains/bio/viktor/F64Array;)I public final fun getF64Buffer ()Lorg/jetbrains/bio/viktor/F64Array; public fun getShape ()[I public static fun getShape-impl (Lorg/jetbrains/bio/viktor/F64Array;)[I diff --git a/settings.gradle.kts b/settings.gradle.kts index ef9000fbb..0f281f46c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,14 +1,13 @@ pluginManagement { repositories { - maven("https://repo.kotlin.link") mavenLocal() + mavenCentral() gradlePluginPortal() - jcenter() - maven("https://dl.bintray.com/kotlin/kotlinx") + maven("https://repo.kotlin.link") } - val toolsVersion = "0.9.5-dev" - val kotlinVersion = "1.5.0-M2" + val toolsVersion = "0.9.5-dev-2" + val kotlinVersion = "1.5.0-RC" plugins { kotlin("multiplatform") version kotlinVersion @@ -40,5 +39,5 @@ include( ":kmath-ast", ":kmath-ejml", ":kmath-kotlingrad", - ":examples" + ":examples", ) From b46e8c5fe23bb64fa6868363848e2e13e0c1edfb Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 14 Apr 2021 22:13:54 +0100 Subject: [PATCH 198/393] LU and det refactored --- .../core/DoubleLinearOpsTensorAlgebra.kt | 64 ++++++------------- .../kscience/kmath/tensors/core/linutils.kt | 43 +++++++++++-- .../core/TestDoubleLinearOpsAlgebra.kt | 8 +-- 3 files changed, 59 insertions(+), 56 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index a6bd5d5f7..e72948c84 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -10,43 +10,15 @@ public class DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, DoubleTensorAlgebra() { - override fun DoubleTensor.inv(): DoubleTensor = invLU() + override fun DoubleTensor.inv(): DoubleTensor = invLU(1e-9) - override fun DoubleTensor.det(): DoubleTensor = detLU() + override fun DoubleTensor.det(): DoubleTensor = detLU(1e-9) - internal fun DoubleTensor.luForDet(forDet: Boolean = false): Pair { - checkSquareMatrix(shape) + public fun DoubleTensor.lu(epsilon: Double): Pair = + computeLU(this, epsilon) ?: + throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon") - val luTensor = copy() - - val n = shape.size - val m = shape.last() - val pivotsShape = IntArray(n - 1) { i -> shape[i] } - pivotsShape[n - 2] = m + 1 - - val pivotsTensor = IntTensor( - pivotsShape, - IntArray(pivotsShape.reduce(Int::times)) { 0 } - ) - - for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) - try { - luHelper(lu.as2D(), pivots.as1D(), m) - } catch (e: RuntimeException) { - if (forDet) { - lu.as2D()[intArrayOf(0, 0)] = 0.0 - } else { - throw IllegalStateException("LUP decomposition can't be performed") - } - } - - - return Pair(luTensor, pivotsTensor) - } - - override fun DoubleTensor.lu(): Pair { - return luForDet(false) - } + override fun DoubleTensor.lu(): Pair = lu(1e-9) override fun luPivot( luTensor: DoubleTensor, @@ -79,9 +51,7 @@ public class DoubleLinearOpsTensorAlgebra : public fun DoubleTensor.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) - checkPositiveDefinite(this) - //checkPositiveDefinite(this, epsilon) - + checkPositiveDefinite(this, epsilon) val n = shape.last() val lTensor = zeroesLike() @@ -139,15 +109,19 @@ public class DoubleLinearOpsTensorAlgebra : val shp = s.shape + intArrayOf(1) val utv = u.transpose() dot v val n = s.shape.last() - for( matrix in utv.matrixSequence()) - cleanSymHelper(matrix.as2D(),n) + for (matrix in utv.matrixSequence()) + cleanSymHelper(matrix.as2D(), n) val eig = (utv dot s.view(shp)).view(s.shape) return Pair(eig, v) } - public fun DoubleTensor.detLU(): DoubleTensor { - val (luTensor, pivotsTensor) = luForDet(forDet = true) + public fun DoubleTensor.detLU(epsilon: Double = 1e-9): DoubleTensor { + + checkSquareMatrix(this.shape) + val luTensor = this.copy() + val pivotsTensor = this.setUpPivots() + val n = shape.size val detTensorShape = IntArray(n - 1) { i -> shape[i] } @@ -160,15 +134,15 @@ public class DoubleLinearOpsTensorAlgebra : ) luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (lu, pivots) -> - resBuffer[index] = luMatrixDet(lu.as2D(), pivots.as1D()) + resBuffer[index] = if (luHelper(lu.as2D(), pivots.as1D(), epsilon)) + 0.0 else luMatrixDet(lu.as2D(), pivots.as1D()) } return detTensor } - public fun DoubleTensor.invLU(): DoubleTensor { - //TODO("Andrei the det is non-zero") - val (luTensor, pivotsTensor) = lu() + public fun DoubleTensor.invLU(epsilon: Double = 1e-9): DoubleTensor { + val (luTensor, pivotsTensor) = lu(epsilon) val invTensor = luTensor.zeroesLike() val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index f2c9d8c76..ee159b614 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -61,7 +61,13 @@ internal inline fun dotHelper( } } -internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStructure1D, m: Int) { +internal inline fun luHelper( + lu: MutableStructure2D, + pivots: MutableStructure1D, + epsilon: Double): Boolean { + + val m = lu.rowNum + for (row in 0..m) pivots[row] = row for (i in 0 until m) { @@ -69,16 +75,15 @@ internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStru var maxInd = i for (k in i until m) { - val absA = kotlin.math.abs(lu[k, i]) + val absA = abs(lu[k, i]) if (absA > maxVal) { maxVal = absA maxInd = k } } - if (abs(maxVal) < 1e-9) { - throw RuntimeException() - } + if (abs(maxVal) < epsilon) + return true // matrix is singular if (maxInd != i) { @@ -103,6 +108,34 @@ internal inline fun luHelper(lu: MutableStructure2D, pivots: MutableStru } } } + return false +} + +internal inline fun BufferedTensor.setUpPivots(): IntTensor { + val n = this.shape.size + val m = this.shape.last() + val pivotsShape = IntArray(n - 1) { i -> this.shape[i] } + pivotsShape[n - 2] = m + 1 + + return IntTensor( + pivotsShape, + IntArray(pivotsShape.reduce(Int::times)) { 0 } + ) +} + +internal inline fun DoubleLinearOpsTensorAlgebra.computeLU( + tensor: DoubleTensor, + epsilon: Double): Pair? { + + checkSquareMatrix(tensor.shape) + val luTensor = tensor.copy() + val pivotsTensor = tensor.setUpPivots() + + for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) + if(luHelper(lu.as2D(), pivots.as1D(), epsilon)) + return null + + return Pair(luTensor, pivotsTensor) } internal inline fun pivInit( diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 75ff12355..d19d0b6f6 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -1,8 +1,6 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.structures.toList import kotlin.math.abs -import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -45,7 +43,7 @@ class TestDoubleLinearOpsTensorAlgebra { ) ) - assertTrue { abs(m.det().value() - expectedValue) < 1e-5} + assertTrue { abs(m.det().value() - expectedValue) < 1e-5 } } @Test @@ -57,7 +55,7 @@ class TestDoubleLinearOpsTensorAlgebra { ) ) - assertTrue { abs(m.det().value() - expectedValue) < 1e-5} + assertTrue { abs(m.det().value() - expectedValue) < 1e-5 } } @Test @@ -144,11 +142,9 @@ class TestDoubleLinearOpsTensorAlgebra { val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) ) - //checkPositiveDefinite(sigma) sigma must be positive definite val low = sigma.cholesky() val sigmChol = low dot low.transpose() assertTrue(sigma.eq(sigmChol)) - } @Test From 0fa73e1e9e4cca8cf4377d580bbfbcceb394d8c0 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 14 Apr 2021 22:21:18 +0100 Subject: [PATCH 199/393] Drop unused code --- .../kotlin/space/kscience/kmath/tensors/core/checks.kt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 45a71d1bc..730b6ed9a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -2,7 +2,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.TensorAlgebra import space.kscience.kmath.tensors.TensorStructure -import kotlin.math.abs internal inline fun , @@ -71,13 +70,4 @@ internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( check(mat.asTensor().detLU().value() > 0.0){ "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" } -} - -internal inline fun DoubleLinearOpsTensorAlgebra.checkNonSingularMatrix(tensor: DoubleTensor): Unit { - for( mat in tensor.matrixSequence()) { - val detTensor = mat.asTensor().detLU() - check(!(detTensor.eq(detTensor.zeroesLike()))){ - "Tensor contains matrices which are singular" - } - } } \ No newline at end of file From 93bc37162201ef1a721bd7026508a7488c576977 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 15 Apr 2021 09:53:29 +0300 Subject: [PATCH 200/393] WIP Integrator tests --- .../kscience/kmath/functions/functionTypes.kt | 7 +++++ .../kmath/integration/GaussIntegrator.kt | 8 +++-- .../integration/GaussIntegratorRuleFactory.kt | 7 +++-- .../kmath/integration/UnivariateIntegrand.kt | 3 +- .../kmath/integration/GaussIntegralTest.kt | 30 +++++++++++++++++++ 5 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/functionTypes.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/functionTypes.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/functionTypes.kt new file mode 100644 index 000000000..788f8bc53 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/functionTypes.kt @@ -0,0 +1,7 @@ +package space.kscience.kmath.functions + +import space.kscience.kmath.structures.Buffer + +public typealias UnivariateFunction = (T) -> T + +public typealias MultivariateFunction = (Buffer) -> T \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index d58b6131f..a4f79f542 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -23,7 +23,7 @@ import space.kscience.kmath.structures.indices /** * A simple one-pass integrator based on Gauss rule */ -public class GaussIntegrator internal constructor( +public class GaussIntegrator> internal constructor( public val algebra: Ring, private val points: Buffer, private val weights: Buffer, @@ -31,6 +31,7 @@ public class GaussIntegrator internal constructor( init { require(points.size == weights.size) { "Inconsistent points and weights sizes" } + require(points.indices.all { i -> i == 0 || points[i] > points[i - 1] }){"Integration nodes must be sorted"} } override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand = with(algebra) { @@ -54,12 +55,13 @@ public class GaussIntegrator internal constructor( range: ClosedRange, numPoints: Int = 100, ruleFactory: GaussIntegratorRuleFactory = GaussLegendreDoubleRuleFactory, + features: List = emptyList(), function: (Double) -> Double, - ): Double { + ): UnivariateIntegrand { val (points, weights) = ruleFactory.build(numPoints, range) return GaussIntegrator(DoubleField, points, weights).integrate( UnivariateIntegrand(function, IntegrationRange(range)) - ).value!! + ) } } } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt index 234859991..a3adacc04 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.integration import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.Ring import space.kscience.kmath.structures.* import kotlin.jvm.Synchronized @@ -8,7 +9,7 @@ import kotlin.math.ulp import kotlin.native.concurrent.ThreadLocal public interface GaussIntegratorRuleFactory { - public val algebra: Ring + public val algebra: Field public val bufferFactory: BufferFactory public fun build(numPoints: Int): Pair, Buffer> @@ -29,7 +30,7 @@ public fun > GaussIntegratorRuleFactory.build( val points = with(algebra) { val length = range.endInclusive - range.start normalized.first.map(bufferFactory) { - range.start + length * it + range.start + length / 2 + length * it/2 } } @@ -46,7 +47,7 @@ public fun > GaussIntegratorRuleFactory.build( @ThreadLocal public object GaussLegendreDoubleRuleFactory : GaussIntegratorRuleFactory { - override val algebra: Ring get() = DoubleField + override val algebra: Field get() = DoubleField override val bufferFactory: BufferFactory get() = ::DoubleBuffer diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index 637761497..9d515e754 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -1,12 +1,13 @@ package space.kscience.kmath.integration +import space.kscience.kmath.functions.UnivariateFunction import space.kscience.kmath.misc.UnstableKMathAPI import kotlin.jvm.JvmInline import kotlin.reflect.KClass public class UnivariateIntegrand internal constructor( private val features: Map, IntegrandFeature>, - public val function: (T) -> T, + public val function: UnivariateFunction, ) : Integrand { @Suppress("UNCHECKED_CAST") diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt new file mode 100644 index 000000000..7c33ea73f --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -0,0 +1,30 @@ +package space.kscience.kmath.integration + +import kotlin.math.PI +import kotlin.math.sin +import kotlin.test.Test +import kotlin.test.assertEquals + +class GaussIntegralTest { + @Test + fun gaussSin() { + val res = GaussIntegrator.integrate(0.0..2 * PI) { x -> + sin(x) + } + assertEquals(0.0, res.value!!, 1e-4) + } + + @Test + fun gaussUniform() { + val res = GaussIntegrator.integrate(0.0..100.0,300) { x -> + if(x in 30.0..50.0){ + 1.0 + } else { + 0.0 + } + } + assertEquals(20.0, res.value!!, 0.1) + } + + +} \ No newline at end of file From 19ec6a57a4bec20fcf14725da84dc125ad539e1f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 15 Apr 2021 19:39:46 +0300 Subject: [PATCH 201/393] Gauss-Legendre working test --- .../integration/GaussIntegratorRuleFactory.kt | 18 +++++++++++------- .../kmath/integration/GaussIntegralTest.kt | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt index a3adacc04..678e6bf0a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt @@ -2,7 +2,6 @@ package space.kscience.kmath.integration import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.Ring import space.kscience.kmath.structures.* import kotlin.jvm.Synchronized import kotlin.math.ulp @@ -27,14 +26,19 @@ public fun > GaussIntegratorRuleFactory.build( range: ClosedRange, ): Pair, Buffer> { val normalized = build(numPoints) - val points = with(algebra) { + with(algebra) { val length = range.endInclusive - range.start - normalized.first.map(bufferFactory) { - range.start + length / 2 + length * it/2 - } - } - return points to normalized.second + val points = normalized.first.map(bufferFactory) { + range.start + length / 2 + length * it / 2 + } + + val weights = normalized.second.map(bufferFactory) { + it * length / 2 + } + + return points to weights + } } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 7c33ea73f..5fccd8aa9 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -23,7 +23,7 @@ class GaussIntegralTest { 0.0 } } - assertEquals(20.0, res.value!!, 0.1) + assertEquals(20.0, res.value!!, 0.5) } From 41b7349a43b234d4563d150bb80db26176152a47 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 23 Mar 2021 22:13:35 +0700 Subject: [PATCH 202/393] Setup copyright headers, add references to third-party files, update LICENSE --- build.gradle.kts | 5 + examples/build.gradle.kts | 5 + .../kmath/benchmarks/ArrayBenchmark.kt | 5 + .../kmath/benchmarks/BufferBenchmark.kt | 5 + .../kscience/kmath/benchmarks/DotBenchmark.kt | 5 + .../ExpressionsInterpretersBenchmark.kt | 5 + .../benchmarks/MatrixInverseBenchmark.kt | 5 + .../kmath/benchmarks/NDFieldBenchmark.kt | 5 + .../kmath/benchmarks/ViktorBenchmark.kt | 5 + .../kmath/benchmarks/ViktorLogBenchmark.kt | 5 + .../space/kscience/kmath/ast/expressions.kt | 5 + .../kscience/kmath/ast/kotlingradSupport.kt | 5 + .../kmath/commons/fit/fitWithAutoDiff.kt | 5 + .../space/kscience/kmath/linear/gradient.kt | 5 + .../kscience/kmath/operations/BigIntDemo.kt | 5 + .../kscience/kmath/operations/ComplexDemo.kt | 5 + .../kmath/stat/DistributionBenchmark.kt | 5 + .../kscience/kmath/stat/DistributionDemo.kt | 5 + .../kscience/kmath/structures/ComplexND.kt | 5 + .../kscience/kmath/structures/NDField.kt | 5 + .../kmath/structures/ParallelRealNDField.kt | 5 + .../structures/StructureReadBenchmark.kt | 5 + .../structures/StructureWriteBenchmark.kt | 5 + .../kmath/structures/typeSafeDimensions.kt | 5 + gradle.properties | 5 + gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 15 +- kmath-ast/build.gradle.kts | 5 + .../kotlin/space/kscience/kmath/ast/MST.kt | 5 + .../space/kscience/kmath/ast/MstAlgebra.kt | 5 + .../space/kscience/kmath/ast/MstExpression.kt | 5 + .../space/kscience/kmath/estree/estree.kt | 5 + .../kmath/estree/internal/ESTreeBuilder.kt | 5 + .../kmath/estree/internal/astring/astring.kt | 5 + .../internal/astring/astring.typealises.kt | 5 + .../kmath/estree/internal/emitter/emitter.kt | 5 + .../internal/estree/estree.extensions.kt | 5 + .../kmath/estree/internal/estree/estree.kt | 5 + .../kmath/estree/internal/stream/stream.kt | 5 + .../internal/tsstdlib/lib.es2015.iterable.kt | 5 + .../kmath/estree/internal/tsstdlib/lib.es5.kt | 5 + .../TestESTreeConsistencyWithInterpreter.kt | 5 + .../estree/TestESTreeOperationsSupport.kt | 5 + .../kmath/estree/TestESTreeSpecialization.kt | 5 + .../kmath/estree/TestESTreeVariables.kt | 5 + .../kotlin/space/kscience/kmath/asm/asm.kt | 5 + .../kscience/kmath/asm/internal/AsmBuilder.kt | 5 + .../kmath/asm/internal/codegenUtils.kt | 5 + .../kmath/asm/internal/mapIntrinsics.kt | 5 + .../kotlin/space/kscience/kmath/ast/parser.kt | 5 + .../asm/TestAsmConsistencyWithInterpreter.kt | 5 + .../kmath/asm/TestAsmOperationsSupport.kt | 5 + .../kmath/asm/TestAsmSpecialization.kt | 5 + .../kscience/kmath/asm/TestAsmVariables.kt | 5 + .../kmath/ast/ParserPrecedenceTest.kt | 5 + .../space/kscience/kmath/ast/ParserTest.kt | 5 + kmath-commons/build.gradle.kts | 5 + .../DerivativeStructureExpression.kt | 5 + .../kscience/kmath/commons/linear/CMMatrix.kt | 5 + .../kscience/kmath/commons/linear/CMSolver.kt | 5 + .../optimization/CMOptimizationProblem.kt | 5 + .../kmath/commons/optimization/cmFit.kt | 5 + .../random/CMRandomGeneratorWrapper.kt | 5 + .../commons/transform/Transformations.kt | 5 + .../DerivativeStructureExpressionTest.kt | 5 + .../commons/optimization/OptimizeTest.kt | 5 + kmath-complex/build.gradle.kts | 5 + .../space/kscience/kmath/complex/Complex.kt | 5 + .../kscience/kmath/complex/ComplexNDField.kt | 5 + .../kscience/kmath/complex/Quaternion.kt | 5 + .../kmath/complex/ComplexBufferSpecTest.kt | 5 + .../kmath/complex/ComplexFieldTest.kt | 5 + .../kscience/kmath/complex/ComplexTest.kt | 5 + .../complex/ExpressionFieldForComplexTest.kt | 5 + .../kmath/complex/QuaternionFieldTest.kt | 5 + kmath-core/build.gradle.kts | 5 + .../space/kscience/kmath/domains/Domain.kt | 5 + .../kmath/domains/HyperSquareDomain.kt | 17 +- .../kscience/kmath/domains/RealDomain.kt | 17 +- .../kmath/domains/UnconstrainedDomain.kt | 17 +- .../kmath/domains/UnivariateDomain.kt | 5 + .../expressions/DifferentiableExpression.kt | 5 + .../kscience/kmath/expressions/Expression.kt | 5 + .../FunctionalExpressionAlgebra.kt | 5 + .../kmath/expressions/SimpleAutoDiff.kt | 5 + .../kmath/expressions/SymbolIndexer.kt | 5 + .../kmath/expressions/expressionBuilders.kt | 5 + .../kmath/linear/BufferedLinearSpace.kt | 5 + .../kscience/kmath/linear/LinearSolver.kt | 5 + .../kscience/kmath/linear/LinearSpace.kt | 5 + .../kscience/kmath/linear/LupDecomposition.kt | 5 + .../kscience/kmath/linear/MatrixBuilder.kt | 5 + .../kscience/kmath/linear/MatrixFeatures.kt | 5 + .../kscience/kmath/linear/MatrixWrapper.kt | 5 + .../kscience/kmath/linear/VirtualMatrix.kt | 5 + .../space/kscience/kmath/misc/annotations.kt | 5 + .../space/kscience/kmath/misc/cumulative.kt | 5 + .../kscience/kmath/nd/BufferNDAlgebra.kt | 5 + .../space/kscience/kmath/nd/NDAlgebra.kt | 5 + .../space/kscience/kmath/nd/NDStructure.kt | 5 + .../space/kscience/kmath/nd/RealNDField.kt | 5 + .../space/kscience/kmath/nd/ShortNDRing.kt | 5 + .../space/kscience/kmath/nd/Structure1D.kt | 5 + .../space/kscience/kmath/nd/Structure2D.kt | 5 + .../kscience/kmath/operations/Algebra.kt | 5 + .../kmath/operations/AlgebraElements.kt | 5 + .../space/kscience/kmath/operations/BigInt.kt | 5 + .../kmath/operations/NumericAlgebra.kt | 5 + .../kmath/operations/OptionalOperations.kt | 5 + .../kmath/operations/algebraExtensions.kt | 5 + .../kscience/kmath/operations/numbers.kt | 5 + .../space/kscience/kmath/structures/Buffer.kt | 5 + .../kmath/structures/BufferAccessor2D.kt | 5 + .../kmath/structures/FlaggedBuffer.kt | 5 + .../kscience/kmath/structures/FloatBuffer.kt | 5 + .../kscience/kmath/structures/IntBuffer.kt | 5 + .../kscience/kmath/structures/LongBuffer.kt | 5 + .../kscience/kmath/structures/MemoryBuffer.kt | 5 + .../kscience/kmath/structures/RealBuffer.kt | 5 + .../kmath/structures/RealBufferField.kt | 5 + .../kscience/kmath/structures/ShortBuffer.kt | 5 + .../kmath/structures/bufferOperation.kt | 5 + .../kmath/expressions/ExpressionFieldTest.kt | 5 + .../kmath/expressions/SimpleAutoDiffTest.kt | 5 + .../space/kscience/kmath/linear/MatrixTest.kt | 5 + .../kscience/kmath/linear/RealLUSolverTest.kt | 5 + .../kscience/kmath/linear/VectorSpaceTest.kt | 5 + .../kscience/kmath/misc/CumulativeKtTest.kt | 5 + .../kmath/operations/BigIntAlgebraTest.kt | 5 + .../kmath/operations/BigIntConstructorTest.kt | 5 + .../kmath/operations/BigIntConversionsTest.kt | 5 + .../kmath/operations/BigIntOperationsTest.kt | 5 + .../kmath/operations/RealFieldTest.kt | 5 + .../kscience/kmath/structures/NDFieldTest.kt | 5 + .../kmath/structures/NumberNDFieldTest.kt | 5 + .../kmath/testutils/AlgebraicVerifier.kt | 5 + .../kscience/kmath/testutils/FieldVerifier.kt | 5 + .../kscience/kmath/testutils/RingVerifier.kt | 5 + .../kscience/kmath/testutils/SpaceVerifier.kt | 5 + .../kscience/kmath/operations/BigNumbers.kt | 5 + kmath-coroutines/build.gradle.kts | 5 + .../kscience/kmath/chains/BlockingIntChain.kt | 5 + .../kmath/chains/BlockingRealChain.kt | 5 + .../space/kscience/kmath/chains/Chain.kt | 15 +- .../space/kscience/kmath/chains/flowExtra.kt | 5 + .../kmath/coroutines/coroutinesExtra.kt | 5 + .../kscience/kmath/streaming/BufferFlow.kt | 5 + .../kscience/kmath/streaming/RingBuffer.kt | 5 + .../space/kscience/kmath/chains/ChainExt.kt | 5 + .../kmath/structures/LazyNDStructure.kt | 5 + .../kmath/streaming/BufferFlowTest.kt | 5 + .../kmath/streaming/RingBufferTest.kt | 5 + kmath-dimensions/build.gradle.kts | 5 + .../kscience/kmath/dimensions/Dimensions.kt | 5 + .../kscience/kmath/dimensions/Wrappers.kt | 5 + .../kscience/dimensions/DMatrixContextTest.kt | 5 + .../space/kscience/kmath/dimensions/dimJs.kt | 5 + .../space/kscience/kmath/dimensions/dimJvm.kt | 5 + .../kscience/kmath/dimensions/dimNative.kt | 5 + kmath-ejml/build.gradle.kts | 5 + .../kscience/kmath/ejml/EjmlLinearSpace.kt | 5 + .../space/kscience/kmath/ejml/EjmlMatrix.kt | 5 + .../space/kscience/kmath/ejml/EjmlVector.kt | 5 + .../kscience/kmath/ejml/EjmlMatrixTest.kt | 5 + .../kscience/kmath/ejml/EjmlVectorTest.kt | 5 + kmath-for-real/build.gradle.kts | 5 + .../space/kscience/kmath/real/RealMatrix.kt | 5 + .../space/kscience/kmath/real/RealVector.kt | 5 + .../kotlin/space/kscience/kmath/real/dot.kt | 5 + .../kotlin/space/kscience/kmath/real/grids.kt | 5 + .../space/kscience/kmath/real/realND.kt | 5 + .../kotlin/kaceince/kmath/real/GridTest.kt | 5 + .../kaceince/kmath/real/RealMatrixTest.kt | 5 + .../kaceince/kmath/real/RealVectorTest.kt | 5 + kmath-functions/build.gradle.kts | 5 + .../kscience/kmath/functions/Piecewise.kt | 5 + .../kscience/kmath/functions/Polynomial.kt | 5 + .../kmath/interpolation/Interpolator.kt | 5 + .../kmath/interpolation/LinearInterpolator.kt | 5 + .../kmath/interpolation/LoessInterpolator.kt | 5 + .../kmath/interpolation/SplineInterpolator.kt | 5 + .../kmath/interpolation/XYPointSet.kt | 5 + .../interpolation/LinearInterpolatorTest.kt | 5 + kmath-geometry/build.gradle.kts | 5 + .../kmath/geometry/Euclidean2DSpace.kt | 5 + .../kmath/geometry/Euclidean3DSpace.kt | 5 + .../kscience/kmath/geometry/GeometrySpace.kt | 5 + .../space/kscience/kmath/geometry/Line.kt | 5 + .../kscience/kmath/geometry/ReferenceFrame.kt | 5 + kmath-histograms/build.gradle.kts | 5 + .../space/kscience/kmath/histogram/Counter.kt | 5 + .../kscience/kmath/histogram/Histogram.kt | 5 + .../kmath/histogram/IndexedHistogramSpace.kt | 5 + .../kmath/histogram/RealHistogramSpace.kt | 5 + .../histogram/MultivariateHistogramTest.kt | 5 + .../kmath/histogram/TreeHistogramSpace.kt | 5 + .../kmath/histogram/UnivariateHistogram.kt | 5 + kmath-kotlingrad/build.gradle.kts | 5 + .../kotlingrad/DifferentiableMstExpression.kt | 5 + .../kscience/kmath/kotlingrad/KMathNumber.kt | 5 + .../kmath/kotlingrad/ScalarsAdapters.kt | 5 + .../kmath/kotlingrad/AdaptingTests.kt | 5 + kmath-memory/build.gradle.kts | 5 + .../space/kscience/kmath/memory/Memory.kt | 5 + .../space/kscience/kmath/memory/MemorySpec.kt | 5 + .../kscience/kmath/memory/DataViewMemory.kt | 5 + .../kscience/kmath/memory/ByteBufferMemory.kt | 5 + .../kscience/kmath/memory/NativeMemory.kt | 5 + kmath-nd4j/build.gradle.kts | 5 + .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 5 + .../kscience/kmath/nd4j/Nd4jArrayIterator.kt | 5 + .../kscience/kmath/nd4j/Nd4jArrayStructure.kt | 5 + .../space/kscience/kmath/nd4j/arrays.kt | 5 + .../kmath/nd4j/Nd4jArrayAlgebraTest.kt | 5 + .../kmath/nd4j/Nd4jArrayStructureTest.kt | 5 + kmath-stat/build.gradle.kts | 5 + .../space/kscience/kmath/stat/Distribution.kt | 5 + .../kmath/stat/FactorizedDistribution.kt | 5 + .../space/kscience/kmath/stat/Fitting.kt | 5 + .../space/kscience/kmath/stat/MCScope.kt | 5 + .../kmath/stat/OptimizationProblem.kt | 5 + .../space/kscience/kmath/stat/RandomChain.kt | 5 + .../kscience/kmath/stat/RandomGenerator.kt | 5 + .../kscience/kmath/stat/SamplerAlgebra.kt | 5 + .../space/kscience/kmath/stat/Statistic.kt | 5 + .../kmath/stat/UniformDistribution.kt | 5 + .../kmath/stat/RandomSourceGenerator.kt | 5 + .../kscience/kmath/stat/distributions.kt | 5 + .../kmath/stat/CommonsDistributionsTest.kt | 5 + .../space/kscience/kmath/stat/MCScopeTest.kt | 5 + .../space/kscience/kmath/stat/SamplerTest.kt | 5 + .../kscience/kmath/stat/StatisticTest.kt | 5 + kmath-viktor/build.gradle.kts | 5 + .../kscience/kmath/viktor/ViktorBuffer.kt | 5 + .../kmath/viktor/ViktorNDStructure.kt | 5 + license/COPYRIGHT.txt | 15 + license/COPYRIGHT_HEADER.txt | 4 + LICENSE => license/LICENSE.txt | 2 +- license/README.md | 17 + license/third_party/cm_license.txt | 457 ++++++++++++++++++ settings.gradle.kts | 5 + 241 files changed, 1662 insertions(+), 69 deletions(-) create mode 100644 license/COPYRIGHT.txt create mode 100644 license/COPYRIGHT_HEADER.txt rename LICENSE => license/LICENSE.txt (99%) create mode 100644 license/README.md create mode 100644 license/third_party/cm_license.txt diff --git a/build.gradle.kts b/build.gradle.kts index 9810e378f..ce9cb1528 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + import ru.mipt.npm.gradle.KSciencePublishingPlugin plugins { diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 0301e4d67..86ffa94a3 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt index 43b698c03..ff933997f 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt @@ -1,3 +1,8 @@ +/* + * 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.benchmarks import kotlinx.benchmark.Benchmark diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt index 1c3bbab75..8df4ce4da 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt @@ -1,3 +1,8 @@ +/* + * 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.benchmarks import kotlinx.benchmark.Benchmark diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt index dbf373929..ad6b8cbd3 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt @@ -1,3 +1,8 @@ +/* + * 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.benchmarks import kotlinx.benchmark.Benchmark diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index e5cfbf9f6..c8e4a5a6f 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -1,3 +1,8 @@ +/* + * 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.benchmarks import kotlinx.benchmark.Benchmark diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt index 7aa8ac975..d1803e389 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt @@ -1,3 +1,8 @@ +/* + * 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.benchmarks import kotlinx.benchmark.Benchmark diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt index aeee0dafe..9a67d2afa 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -1,3 +1,8 @@ +/* + * 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.benchmarks import kotlinx.benchmark.Benchmark diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt index c511173a9..4aac2568e 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt @@ -1,3 +1,8 @@ +/* + * 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.benchmarks import kotlinx.benchmark.Benchmark diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt index 0036b615c..cd4b18f7b 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt @@ -1,3 +1,8 @@ +/* + * 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.benchmarks import kotlinx.benchmark.Benchmark diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt index c342fc3ef..c4531df51 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt @@ -1,3 +1,8 @@ +/* + * 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.ast import space.kscience.kmath.expressions.invoke diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt index 16304a458..de784fbef 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt @@ -1,3 +1,8 @@ +/* + * 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.ast import space.kscience.kmath.asm.compile diff --git a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt index 63b819dc9..a569e7bb0 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -1,3 +1,8 @@ +/* + * 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.commons.fit import kotlinx.html.br diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt index 8dd3d7f6b..77bb75a5f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt @@ -1,3 +1,8 @@ +/* + * 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.linear import space.kscience.kmath.real.* diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt index 6d5903cae..51f439612 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt @@ -1,3 +1,8 @@ +/* + * 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.operations fun main() { diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/ComplexDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/ComplexDemo.kt index 5330d9e40..324ce641f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/operations/ComplexDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/operations/ComplexDemo.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import space.kscience.kmath.complex.Complex diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt index 1761ed1b5..eb50b26be 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt @@ -1,3 +1,8 @@ +/* + * 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 kscience.kmath.commons.prob import kotlinx.coroutines.Dispatchers diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt index 47b8d8111..0883e70c5 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import kotlinx.coroutines.runBlocking diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt index b8cbc9a57..90e54bbd8 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:Suppress("unused") package space.kscience.kmath.structures diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt index 10fb3cb3d..65f1d13a5 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import kotlinx.coroutines.GlobalScope diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt index 0c914468d..596142013 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/ParallelRealNDField.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt index 7f6d73394..095467e5a 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import space.kscience.kmath.nd.DefaultStrides diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt index 66d85edff..f087a7166 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import space.kscience.kmath.nd.NDStructure diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt index d2d130ab4..955f86fa9 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import space.kscience.kmath.dimensions.D2 diff --git a/gradle.properties b/gradle.properties index 7ff50a435..3aaade368 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,8 @@ +# +# 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. +# + kotlin.code.style=official kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.mpp.stability.nowarn=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 442d9132e..2059e8ea0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,3 +1,8 @@ +# +# 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. +# + distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip diff --git a/gradlew b/gradlew index 4f906e0c8..6ad9eb930 100755 --- a/gradlew +++ b/gradlew @@ -1,19 +1,8 @@ #!/usr/bin/env sh # -# Copyright 2015 the original author or authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 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. # ############################################################################## diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 5b764459c..76a78a271 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + import ru.mipt.npm.gradle.Maturity plugins { diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt index c459d7ff5..468b919c1 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt @@ -1,3 +1,8 @@ +/* + * 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.ast import space.kscience.kmath.operations.Algebra diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt index 5ed39687b..519a93dc6 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt @@ -1,3 +1,8 @@ +/* + * 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.ast import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt index 63dfb38f7..9329d5877 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstExpression.kt @@ -1,3 +1,8 @@ +/* + * 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.ast import space.kscience.kmath.expressions.* diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt index 0bd9a386d..909e8e575 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt @@ -1,3 +1,8 @@ +/* + * 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.estree import space.kscience.kmath.ast.MST diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt index b4de9968d..b7dfc31af 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -1,3 +1,8 @@ +/* + * 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.estree.internal import space.kscience.kmath.estree.internal.astring.generate diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.kt index 1b7500ddb..354757b83 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:JsModule("astring") @file:JsNonModule diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt index 9e75a97c7..eb5c1e3dd 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt @@ -1,3 +1,8 @@ +/* + * 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.estree.internal.astring internal typealias Generator = Any diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/emitter/emitter.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/emitter/emitter.kt index 3028656f5..7707f53a2 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/emitter/emitter.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/emitter/emitter.kt @@ -1,3 +1,8 @@ +/* + * 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.estree.internal.emitter internal open external class Emitter { diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.extensions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.extensions.kt index 0e088c717..9ba11e085 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.extensions.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.extensions.kt @@ -1,3 +1,8 @@ +/* + * 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.estree.internal.estree internal fun Program(sourceType: String, vararg body: dynamic) = object : Program { diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.kt index 4dc1bfc10..a0e42db5d 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.kt @@ -1,3 +1,8 @@ +/* + * 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.estree.internal.estree import kotlin.js.RegExp diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/stream/stream.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/stream/stream.kt index c3477c482..4bdeeea0b 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/stream/stream.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/stream/stream.kt @@ -1,3 +1,8 @@ +/* + * 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.estree.internal.stream import space.kscience.kmath.estree.internal.emitter.Emitter diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt index 7f2975219..a3c721ed4 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt @@ -1,3 +1,8 @@ +/* + * 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.estree.internal.tsstdlib internal external interface IteratorYieldResult { diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt index 7286b4a20..d2413b3e3 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:Suppress("UNUSED_TYPEALIAS_PARAMETER", "DEPRECATION") package space.kscience.kmath.estree.internal.tsstdlib diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt index bb34254b1..99f037b7c 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt @@ -1,3 +1,8 @@ +/* + * 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.estree import space.kscience.kmath.ast.* diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt index 27bf2f167..834495990 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt @@ -1,3 +1,8 @@ +/* + * 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.estree import space.kscience.kmath.ast.mstInExtendedField diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt index c5e43241a..8824b08af 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt @@ -1,3 +1,8 @@ +/* + * 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.estree import space.kscience.kmath.ast.mstInField diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt index ee8f4c6f5..5af26e147 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt @@ -1,3 +1,8 @@ +/* + * 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.estree import space.kscience.kmath.ast.mstInRing diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt index 8875bd715..d2a6505a0 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt @@ -1,3 +1,8 @@ +/* + * 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.asm import space.kscience.kmath.asm.internal.AsmBuilder diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt index a03af5bf9..55fbe5d70 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt @@ -1,3 +1,8 @@ +/* + * 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.asm.internal import org.objectweb.asm.* diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt index 1124a860f..de73c3748 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt @@ -1,3 +1,8 @@ +/* + * 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.asm.internal import org.objectweb.asm.* diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt index f54bc070c..8f4daecf9 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:JvmName("MapIntrinsics") package space.kscience.kmath.asm.internal diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt index 9a38ce81a..b2157558e 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + // TODO move to common when https://github.com/h0tk3y/better-parse/pull/37 is merged package space.kscience.kmath.ast diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt index 7cc1497d0..e16311215 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt @@ -1,3 +1,8 @@ +/* + * 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.asm import space.kscience.kmath.ast.* diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt index e99075f07..4caa35080 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt @@ -1,3 +1,8 @@ +/* + * 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.asm import space.kscience.kmath.ast.mstInExtendedField diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt index a214ca4ad..330cb969f 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt @@ -1,3 +1,8 @@ +/* + * 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.asm import space.kscience.kmath.ast.mstInField diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt index d1aaefffe..71fa99747 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt @@ -1,3 +1,8 @@ +/* + * 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.asm import space.kscience.kmath.ast.mstInRing diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt index 7153f4bfc..b09a04f23 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt @@ -1,3 +1,8 @@ +/* + * 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.ast import space.kscience.kmath.operations.Field diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt index 6807d5c5d..ae2c000bf 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt @@ -1,3 +1,8 @@ +/* + * 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.ast import space.kscience.kmath.complex.Complex diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index 4fe16605a..e73c4e527 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + plugins { id("ru.mipt.npm.gradle.jvm") } diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index b74167c3f..aec62b264 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -1,3 +1,8 @@ +/* + * 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.commons.expressions import org.apache.commons.math3.analysis.differentiation.DerivativeStructure diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index 4671598f7..65ce2f3a3 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -1,3 +1,8 @@ +/* + * 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.commons.linear import org.apache.commons.math3.linear.* diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt index b5fd0154e..de8f9b4ce 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt @@ -1,3 +1,8 @@ +/* + * 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.commons.linear import org.apache.commons.math3.linear.* diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt index d655b4f61..8b943ad8b 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizationProblem.kt @@ -1,3 +1,8 @@ +/* + * 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.commons.optimization import org.apache.commons.math3.optim.* diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt index 5ecd5b756..14e995445 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt @@ -1,3 +1,8 @@ +/* + * 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.commons.optimization import org.apache.commons.math3.analysis.differentiation.DerivativeStructure diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt index 3fd98d097..16a6967e2 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt @@ -1,3 +1,8 @@ +/* + * 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.commons.random import space.kscience.kmath.stat.RandomGenerator diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt index e174a237f..93fa56322 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt @@ -1,3 +1,8 @@ +/* + * 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.commons.transform import kotlinx.coroutines.FlowPreview diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt index 19b6e28da..6e3088dc7 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt @@ -1,3 +1,8 @@ +/* + * 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.commons.expressions import space.kscience.kmath.expressions.* diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt index d29934a4d..404215f71 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -1,3 +1,8 @@ +/* + * 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.commons.optimization import org.junit.jupiter.api.Test diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index 4cd43c70c..876e325d0 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + import ru.mipt.npm.gradle.Maturity plugins { diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt index a73fb0201..21e223306 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt @@ -1,3 +1,8 @@ +/* + * 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.complex import space.kscience.kmath.memory.MemoryReader diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt index 382659e10..497d96cc2 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexNDField.kt @@ -1,3 +1,8 @@ +/* + * 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.complex import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index d391aff18..a09f02f0f 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -1,3 +1,8 @@ +/* + * 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.complex import space.kscience.kmath.memory.MemoryReader diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexBufferSpecTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexBufferSpecTest.kt index e265e5896..17a077ea7 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexBufferSpecTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexBufferSpecTest.kt @@ -1,3 +1,8 @@ +/* + * 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.complex import space.kscience.kmath.structures.Buffer diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt index e00b92077..cbaaa815b 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt @@ -1,3 +1,8 @@ +/* + * 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.complex import space.kscience.kmath.operations.invoke diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexTest.kt index e272f502f..7ad7f883d 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexTest.kt @@ -1,3 +1,8 @@ +/* + * 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.complex import space.kscience.kmath.operations.invoke diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt index 81a131318..8dd27d588 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt @@ -1,3 +1,8 @@ +/* + * 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.complex import space.kscience.kmath.expressions.FunctionalExpressionField diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionFieldTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionFieldTest.kt index 5ce81a251..6784f3516 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionFieldTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionFieldTest.kt @@ -1,3 +1,8 @@ +/* + * 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.complex import space.kscience.kmath.operations.invoke diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 8d30f1d6e..4f1028095 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + import ru.mipt.npm.gradle.Maturity plugins { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt index edf19de55..e6e703cbf 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt @@ -1,3 +1,8 @@ +/* + * 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.domains import space.kscience.kmath.linear.Point diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt index c948f8672..c71f2fd33 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt @@ -1,17 +1,6 @@ -/* - * Copyright 2015 Alexander Nozik. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. +/* + * 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.domains diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt index c20cbfec1..861fc9375 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/RealDomain.kt @@ -1,17 +1,6 @@ -/* - * Copyright 2015 Alexander Nozik. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. +/* + * 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.domains diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt index 002caac50..43d9d27a6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt @@ -1,17 +1,6 @@ -/* - * Copyright 2015 Alexander Nozik. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. +/* + * 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.domains diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt index d20349960..fff9a4ca3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnivariateDomain.kt @@ -1,3 +1,8 @@ +/* + * 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.domains import space.kscience.kmath.linear.Point diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt index 5cbc4dbf4..33d72afad 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt @@ -1,3 +1,8 @@ +/* + * 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.expressions /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt index 5ba24aa62..597b51791 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt @@ -1,3 +1,8 @@ +/* + * 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.expressions import space.kscience.kmath.operations.Algebra diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index cca75754f..aa0815155 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -1,3 +1,8 @@ +/* + * 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.expressions import space.kscience.kmath.operations.* diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt index 4b5b3311e..0774d7211 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -1,3 +1,8 @@ +/* + * 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.expressions import space.kscience.kmath.linear.Point diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt index 580acaafb..7bb74d125 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt @@ -1,3 +1,8 @@ +/* + * 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.expressions import space.kscience.kmath.linear.Point diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt index fbf080032..37a75abc1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt @@ -1,3 +1,8 @@ +/* + * 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.expressions import space.kscience.kmath.operations.ExtendedField diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt index fe92a711a..7a8cf9744 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt @@ -1,3 +1,8 @@ +/* + * 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.linear import space.kscience.kmath.nd.* diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt index af136c552..0b24d212d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt @@ -1,3 +1,8 @@ +/* + * 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.linear import space.kscience.kmath.nd.as1D diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index e8c7d119b..094656aa6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -1,3 +1,8 @@ +/* + * 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.linear import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt index eed50ec28..e1b16e64e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt @@ -1,3 +1,8 @@ +/* + * 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.linear import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt index b30d621fe..e6115a1e5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt @@ -1,3 +1,8 @@ +/* + * 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.linear import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt index 6b97e89ef..21f0b969d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt @@ -1,3 +1,8 @@ +/* + * 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.linear /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt index 97f0acd61..ec90c1e39 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt @@ -1,3 +1,8 @@ +/* + * 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.linear import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt index 8efa08f81..bd9d82fe7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt @@ -1,3 +1,8 @@ +/* + * 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.linear import space.kscience.kmath.nd.NDStructure diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt index 7fd7b433d..206e4e000 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt @@ -1,3 +1,8 @@ +/* + * 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.misc @RequiresOptIn("This API is unstable and could change in future", RequiresOptIn.Level.WARNING) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt index b50e095cf..a4a37e717 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt @@ -1,3 +1,8 @@ +/* + * 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.misc import space.kscience.kmath.operations.Group diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt index bce3a0830..e1545c4d0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferNDAlgebra.kt @@ -1,3 +1,8 @@ +/* + * 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.nd import space.kscience.kmath.operations.* diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt index 5514a8f0f..5730377e6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDAlgebra.kt @@ -1,3 +1,8 @@ +/* + * 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.nd import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt index d758f195d..620f52edf 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/NDStructure.kt @@ -1,3 +1,8 @@ +/* + * 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.nd import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt index 9f1f14af1..448abd571 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/RealNDField.kt @@ -1,3 +1,8 @@ +/* + * 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.nd import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt index 2085840a4..baf1c5732 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortNDRing.kt @@ -1,3 +1,8 @@ +/* + * 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.nd import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index ac8714803..c607728ef 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -1,3 +1,8 @@ +/* + * 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.nd import space.kscience.kmath.structures.Buffer diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 60dedc933..dc568a513 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -1,3 +1,8 @@ +/* + * 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.nd import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 9f57bc4c1..300e1cb44 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import space.kscience.kmath.expressions.Symbol diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt index b2b5911df..c9337d369 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 7e6a2eb81..7756ec22e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt index bd5f5951f..19933fda9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt index 6e6249dfe..8e3e6c777 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 9a395b0f4..a32c7c981 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -1,3 +1,8 @@ +/* + * 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.operations /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt index 4841e78d6..d8243868b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import kotlin.math.pow as kpow diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 1d40a2f2e..9201b5b1d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import kotlin.reflect.KClass diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt index c65af7a98..bc2cb3348 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import space.kscience.kmath.nd.DefaultStrides diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt index 3326c1491..65be5d052 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import kotlin.experimental.and diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt index 5c4ec3b05..95837796d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt @@ -1,3 +1,8 @@ +/* + * 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.structures /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt index 32dfcf9aa..e2b3d0fd6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt @@ -1,3 +1,8 @@ +/* + * 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.structures /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt index 48b1d7a7b..d03957d8f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt @@ -1,3 +1,8 @@ +/* + * 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.structures /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt index 50a2db590..8c98ab9c8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import space.kscience.kmath.memory.* diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt index b56c03b76..2df33b5a5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBuffer.kt @@ -1,3 +1,8 @@ +/* + * 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.structures /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt index 2a03a36e3..5658ce83f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/RealBufferField.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import space.kscience.kmath.operations.ExtendedField diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt index 7832bb863..9ed507d3f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt @@ -1,3 +1,8 @@ +/* + * 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.structures /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt index 4355ba17f..3ec403bdd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/bufferOperation.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt index cf75eba3e..313dd8393 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt @@ -1,3 +1,8 @@ +/* + * 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.expressions import space.kscience.kmath.operations.RealField diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt index ee7fffa4c..0672cc4c7 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -1,3 +1,8 @@ +/* + * 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.expressions import space.kscience.kmath.operations.RealField diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt index 097703f49..5569743cd 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt @@ -1,3 +1,8 @@ +/* + * 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.linear import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt index e6efc6a8a..eb62b36c3 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/RealLUSolverTest.kt @@ -1,3 +1,8 @@ +/* + * 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.linear import space.kscience.kmath.misc.UnstableKMathAPI diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/VectorSpaceTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/VectorSpaceTest.kt index e69de29bb..f2c7f1f90 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/VectorSpaceTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/VectorSpaceTest.kt @@ -0,0 +1,5 @@ +/* + * 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. + */ + diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/CumulativeKtTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/CumulativeKtTest.kt index dfdd3e18e..e5f3f337f 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/CumulativeKtTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/CumulativeKtTest.kt @@ -1,3 +1,8 @@ +/* + * 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.misc import kotlin.test.Test diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt index 93237c7eb..5df89a385 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import space.kscience.kmath.testutils.RingVerifier diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConstructorTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConstructorTest.kt index 59fd7e383..eec3dc3bf 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConstructorTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConstructorTest.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import kotlin.test.Test diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt index ce599e1d1..a2832e531 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import kotlin.test.Test diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt index 26e0c1d98..ae34dbc04 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import kotlin.test.Test diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/RealFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/RealFieldTest.kt index bba612d12..d6636550f 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/RealFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/RealFieldTest.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import space.kscience.kmath.testutils.FieldVerifier diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt index 3c84d7b4b..0257dec9e 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import space.kscience.kmath.nd.NDAlgebra diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt index e9e6e92fb..95c09d24f 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import space.kscience.kmath.linear.LinearSpace diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/AlgebraicVerifier.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/AlgebraicVerifier.kt index 7474aae8f..ddd8fc3ea 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/AlgebraicVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/AlgebraicVerifier.kt @@ -1,3 +1,8 @@ +/* + * 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.testutils import space.kscience.kmath.operations.Algebra diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt index cdb0a7c5d..bd09ff449 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt @@ -1,3 +1,8 @@ +/* + * 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.testutils import space.kscience.kmath.operations.Field diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt index 6970c8ac7..885857f04 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt @@ -1,3 +1,8 @@ +/* + * 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.testutils import space.kscience.kmath.operations.Ring diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt index a9cd4454c..71bd6f879 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt @@ -1,3 +1,8 @@ +/* + * 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.testutils import space.kscience.kmath.operations.Group diff --git a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt index 0ac0ba1c5..9b46369bb 100644 --- a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt +++ b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt @@ -1,3 +1,8 @@ +/* + * 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.operations import java.math.BigDecimal diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index 4a9ca5244..722c7adee 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + plugins { id("ru.mipt.npm.gradle.mpp") } kotlin.sourceSets { diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt index 11da7e503..2186cb85f 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt @@ -1,3 +1,8 @@ +/* + * 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.chains /** diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingRealChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingRealChain.kt index ac6b117dc..5ff271721 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingRealChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingRealChain.kt @@ -1,3 +1,8 @@ +/* + * 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.chains /** diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt index 5375113fe..55cfd6523 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt @@ -1,17 +1,6 @@ /* - * Copyright 2018 Alexander Nozik. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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.chains diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt index 81b4327fc..2bdb9334e 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt @@ -1,3 +1,8 @@ +/* + * 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.chains import kotlinx.coroutines.ExperimentalCoroutinesApi diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt index 6578af0e9..c796a14c2 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt @@ -1,3 +1,8 @@ +/* + * 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.coroutines import kotlinx.coroutines.* diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt index 4df22c2ad..00b19c655 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt @@ -1,3 +1,8 @@ +/* + * 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.streaming import kotlinx.coroutines.FlowPreview diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt index efed41112..395613ef2 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt @@ -1,3 +1,8 @@ +/* + * 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.streaming import kotlinx.coroutines.sync.Mutex diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/chains/ChainExt.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/chains/ChainExt.kt index c62785060..dd6e39071 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/chains/ChainExt.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/chains/ChainExt.kt @@ -1,3 +1,8 @@ +/* + * 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.chains import kotlinx.coroutines.runBlocking diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyNDStructure.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyNDStructure.kt index 51a79f44a..0241c32f7 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyNDStructure.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyNDStructure.kt @@ -1,3 +1,8 @@ +/* + * 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.structures import kotlinx.coroutines.* diff --git a/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/BufferFlowTest.kt b/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/BufferFlowTest.kt index 589456843..9b67f7253 100644 --- a/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/BufferFlowTest.kt +++ b/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/BufferFlowTest.kt @@ -1,3 +1,8 @@ +/* + * 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.streaming import kotlinx.coroutines.* diff --git a/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/RingBufferTest.kt b/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/RingBufferTest.kt index 4a7109310..32e3b2c74 100644 --- a/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/RingBufferTest.kt +++ b/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/RingBufferTest.kt @@ -1,3 +1,8 @@ +/* + * 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.streaming import kotlinx.coroutines.flow.* diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index 3355eda42..0702d4bc8 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + plugins { id("ru.mipt.npm.gradle.mpp") id("ru.mipt.npm.gradle.native") diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimensions.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimensions.kt index 9f0d868f2..8b17d252f 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimensions.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimensions.kt @@ -1,3 +1,8 @@ +/* + * 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.dimensions import kotlin.reflect.KClass diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt index f7e14b29f..3f7dcadc4 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt @@ -1,3 +1,8 @@ +/* + * 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.dimensions import space.kscience.kmath.linear.* diff --git a/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt b/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt index e2a9628ac..c9d5ee6e7 100644 --- a/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt +++ b/kmath-dimensions/src/commonTest/kotlin/kscience/dimensions/DMatrixContextTest.kt @@ -1,3 +1,8 @@ +/* + * 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 kscience.dimensions import space.kscience.kmath.dimensions.D2 diff --git a/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/dimJs.kt b/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/dimJs.kt index 40c1148cb..27912f5bc 100644 --- a/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/dimJs.kt +++ b/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/dimJs.kt @@ -1,3 +1,8 @@ +/* + * 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.dimensions import kotlin.reflect.KClass diff --git a/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/dimJvm.kt b/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/dimJvm.kt index 87df1c097..f21a3e18f 100644 --- a/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/dimJvm.kt +++ b/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/dimJvm.kt @@ -1,3 +1,8 @@ +/* + * 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.dimensions import kotlin.reflect.KClass diff --git a/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/dimNative.kt b/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/dimNative.kt index 3b9728328..9aa58e64a 100644 --- a/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/dimNative.kt +++ b/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/dimNative.kt @@ -1,3 +1,8 @@ +/* + * 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.dimensions import kotlin.native.concurrent.ThreadLocal diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index 07f95b13f..f1286310c 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + plugins { id("ru.mipt.npm.gradle.jvm") } diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index 452280295..3905d9418 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -1,3 +1,8 @@ +/* + * 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.ejml import org.ejml.dense.row.factory.DecompositionFactory_DDRM diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index 5f93af729..656871034 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -1,3 +1,8 @@ +/* + * 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.ejml import org.ejml.simple.SimpleMatrix diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt index efa1f6128..ddf543d91 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt @@ -1,3 +1,8 @@ +/* + * 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.ejml import org.ejml.simple.SimpleMatrix diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt index 70b2ce723..e4a65858e 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -1,3 +1,8 @@ +/* + * 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.ejml import org.ejml.dense.row.factory.DecompositionFactory_DDRM diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt index 1924696fb..e1bcd269e 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt @@ -1,3 +1,8 @@ +/* + * 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.ejml import org.ejml.simple.SimpleMatrix diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index d095cac04..c2be77d5f 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + plugins { id("ru.mipt.npm.gradle.mpp") } diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt index 76c73ab16..b2c391c3b 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt @@ -1,3 +1,8 @@ +/* + * 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.real import space.kscience.kmath.linear.* diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt index 8cc128947..a0802f5e0 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealVector.kt @@ -1,3 +1,8 @@ +/* + * 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.real import space.kscience.kmath.linear.Point diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt index 0bc5c111b..de8cda355 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt @@ -1,3 +1,8 @@ +/* + * 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.real import space.kscience.kmath.linear.LinearSpace diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt index 8b4f1cd96..d89d48db5 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt @@ -1,3 +1,8 @@ +/* + * 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.real import space.kscience.kmath.structures.asBuffer diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt index 492e40922..ff4414efe 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt @@ -1,3 +1,8 @@ +/* + * 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.real import space.kscience.kmath.nd.NDBuffer diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt index c538a2d99..9e27071cf 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt @@ -1,3 +1,8 @@ +/* + * 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 kaceince.kmath.real import space.kscience.kmath.real.step diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt index 06135598e..924e2fcf4 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealMatrixTest.kt @@ -1,3 +1,8 @@ +/* + * 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 kaceince.kmath.real import space.kscience.kmath.linear.LinearSpace diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt index 60d85fda3..7f9eb0f16 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/RealVectorTest.kt @@ -1,3 +1,8 @@ +/* + * 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 kaceince.kmath.real import space.kscience.kmath.linear.LinearSpace diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index fc52c4981..0a3c1cfb5 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + plugins { id("ru.mipt.npm.gradle.mpp") } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index d2470a4b4..eb30d048d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -1,3 +1,8 @@ +/* + * 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 diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 049909fe1..bbe3f00d4 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -1,3 +1,8 @@ +/* + * 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.Group diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt index dc5227f8b..052fe74ae 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -1,3 +1,8 @@ +/* + * 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.interpolation import space.kscience.kmath.functions.PiecewisePolynomial diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt index c939384e3..06db47f24 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt @@ -1,3 +1,8 @@ +/* + * 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.interpolation import space.kscience.kmath.functions.OrderedPiecewisePolynomial diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LoessInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LoessInterpolator.kt index 26e7a4072..ea8255f38 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LoessInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LoessInterpolator.kt @@ -1,3 +1,8 @@ +/* + * 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.interpolation // //import space.kscience.kmath.functions.PiecewisePolynomial diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index ddbe743f0..b4b009426 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -1,3 +1,8 @@ +/* + * 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.interpolation import space.kscience.kmath.functions.OrderedPiecewisePolynomial diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt index c3bcad846..fa5315e94 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/XYPointSet.kt @@ -1,3 +1,8 @@ +/* + * 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.interpolation import space.kscience.kmath.nd.Structure2D diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt index 0b7b62147..8293a9e19 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt @@ -1,3 +1,8 @@ +/* + * 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.interpolation import space.kscience.kmath.functions.PiecewisePolynomial diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index e99eee38b..bccba0601 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + plugins { id("ru.mipt.npm.gradle.mpp") } kotlin.sourceSets.commonMain { diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt index 54a1e032c..a36208ee5 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt @@ -1,3 +1,8 @@ +/* + * 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.geometry import space.kscience.kmath.linear.Point diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt index ed110e383..0f2ac1c87 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt @@ -1,3 +1,8 @@ +/* + * 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.geometry import space.kscience.kmath.linear.Point diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt index 9552c1320..d4245c744 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt @@ -1,3 +1,8 @@ +/* + * 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.geometry import space.kscience.kmath.operations.Group diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt index 89cc46958..5a6d23709 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt @@ -1,3 +1,8 @@ +/* + * 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.geometry public data class Line(val base: V, val direction: V) diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/ReferenceFrame.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/ReferenceFrame.kt index 9197cfed7..a7a28b596 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/ReferenceFrame.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/ReferenceFrame.kt @@ -1,3 +1,8 @@ +/* + * 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.geometry public interface ReferenceFrame diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index 1337e40aa..2ff5807c9 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + plugins { id("ru.mipt.npm.gradle.mpp") } diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt index d5f3965d9..988fd4294 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt @@ -1,3 +1,8 @@ +/* + * 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.histogram import kotlinx.atomicfu.atomic diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt index 9ee4a6e1e..cf53b5079 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt @@ -1,3 +1,8 @@ +/* + * 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.histogram import space.kscience.kmath.domains.Domain diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt index 19128b2ac..960d3400e 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt @@ -1,3 +1,8 @@ +/* + * 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.histogram import space.kscience.kmath.domains.Domain diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt index 3df0b1626..56a8b0e9a 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/RealHistogramSpace.kt @@ -1,3 +1,8 @@ +/* + * 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.histogram import space.kscience.kmath.domains.Domain diff --git a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt index e83f42b4b..92a308d02 100644 --- a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt @@ -1,3 +1,8 @@ +/* + * 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.histogram import space.kscience.kmath.operations.invoke diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt index b2071fa02..5a217f6c2 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt @@ -1,3 +1,8 @@ +/* + * 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.histogram import space.kscience.kmath.domains.UnivariateDomain diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt index 03bd096d9..278f65ce2 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt @@ -1,3 +1,8 @@ +/* + * 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.histogram import space.kscience.kmath.domains.UnivariateDomain diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index 51292cbfb..fbeee2b95 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + plugins { id("ru.mipt.npm.gradle.jvm") } diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt index 39a7248b4..78161cbb9 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -1,3 +1,8 @@ +/* + * 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.kotlingrad import edu.umontreal.kotlingrad.api.SFun diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt index d2edb4376..0c3768dcc 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt @@ -1,3 +1,8 @@ +/* + * 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.kotlingrad import edu.umontreal.kotlingrad.api.RealNumber diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt index 82b801f91..fdab303c1 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -1,3 +1,8 @@ +/* + * 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.kotlingrad import edu.umontreal.kotlingrad.api.* diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index ffdabaffb..9311e5ec2 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -1,3 +1,8 @@ +/* + * 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.kotlingrad import edu.umontreal.kotlingrad.api.* diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index dbd68b042..355afa5bb 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + plugins { id("ru.mipt.npm.gradle.mpp") id("ru.mipt.npm.gradle.native") diff --git a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt index a18d25f7b..930b21095 100644 --- a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt +++ b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt @@ -1,3 +1,8 @@ +/* + * 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.memory import kotlin.contracts.InvocationKind diff --git a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt index 7c68e3abb..d09a50f30 100644 --- a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt +++ b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt @@ -1,3 +1,8 @@ +/* + * 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.memory /** diff --git a/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt b/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt index 38ea8a62e..9a622ea36 100644 --- a/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt +++ b/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt @@ -1,3 +1,8 @@ +/* + * 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.memory import org.khronos.webgl.ArrayBuffer diff --git a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt index 5145b1ed4..5ae3c279f 100644 --- a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt +++ b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt @@ -1,3 +1,8 @@ +/* + * 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.memory import java.io.IOException diff --git a/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt b/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt index 3afb6c7a2..94532fb77 100644 --- a/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt +++ b/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt @@ -1,3 +1,8 @@ +/* + * 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.memory @PublishedApi diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index c801f8e51..f268884c1 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + import ru.mipt.npm.gradle.Maturity plugins { diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index d8ce1052a..2bede1402 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -1,3 +1,8 @@ +/* + * 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.nd4j import org.nd4j.linalg.api.ndarray.INDArray diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt index 521c8cab3..77e1edd5f 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt @@ -1,3 +1,8 @@ +/* + * 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.nd4j import org.nd4j.linalg.api.ndarray.INDArray diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt index 415c908a8..70b2570c9 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt @@ -1,3 +1,8 @@ +/* + * 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.nd4j import org.nd4j.linalg.api.ndarray.INDArray diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt index 519c660e8..6c414cc13 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt @@ -1,3 +1,8 @@ +/* + * 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.nd4j internal fun IntArray.toLongArray(): LongArray = LongArray(size) { this[it].toLong() } diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt index 9a067aa29..5ada02d4b 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt @@ -1,3 +1,8 @@ +/* + * 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.nd4j import org.nd4j.linalg.factory.Nd4j diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt index 03369127d..f05bf9c84 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt @@ -1,3 +1,8 @@ +/* + * 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.nd4j import org.nd4j.linalg.factory.Nd4j diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index 67a96937c..28361c0bc 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + plugins { id("ru.mipt.npm.gradle.mpp") } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt index b5b6db1d8..8b89f5ea1 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import space.kscience.kmath.chains.Chain diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/FactorizedDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/FactorizedDistribution.kt index ff7a13652..a57a0af4d 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/FactorizedDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/FactorizedDistribution.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import space.kscience.kmath.chains.Chain diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Fitting.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Fitting.kt index b006c8ba2..56ab8e06a 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Fitting.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Fitting.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import space.kscience.kmath.expressions.* diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt index d89d74914..9e5c70a26 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import kotlinx.coroutines.* diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt index 71f3096de..d881f881c 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/OptimizationProblem.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import space.kscience.kmath.expressions.DifferentiableExpression diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt index 881eabdac..20dd8cf20 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import space.kscience.kmath.chains.Chain diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt index 1a4f3b75d..02f2ff33c 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import kotlin.random.Random diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt index c5ec99dae..763f01018 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import space.kscience.kmath.chains.Chain diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt index a9f7cd3e4..b55555563 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import kotlinx.coroutines.CoroutineDispatcher diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt index 4fc0905b8..8204e8593 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import space.kscience.kmath.chains.Chain diff --git a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt index 9e752d571..309d26b4d 100644 --- a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt +++ b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import org.apache.commons.rng.UniformRandomProvider diff --git a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt index d33b54818..cfd0538df 100644 --- a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt +++ b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import org.apache.commons.rng.UniformRandomProvider diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt index 70708a5c8..39f593dbe 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import kotlinx.coroutines.flow.take diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt index 9eada43f9..075d7f3e5 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import kotlinx.coroutines.* diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/SamplerTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/SamplerTest.kt index 244b5107f..b55940815 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/SamplerTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/SamplerTest.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import kotlinx.coroutines.runBlocking diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt index 156e618f9..c747749ce 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt @@ -1,3 +1,8 @@ +/* + * 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.stat import kotlinx.coroutines.flow.drop diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index b79a25ea1..d28862d01 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + plugins { id("ru.mipt.npm.gradle.jvm") } diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt index 1592763db..9e24bf43d 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt @@ -1,3 +1,8 @@ +/* + * 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.viktor import org.jetbrains.bio.viktor.F64FlatArray diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt index d791ed675..89c2e5967 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorNDStructure.kt @@ -1,3 +1,8 @@ +/* + * 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.viktor import org.jetbrains.bio.viktor.F64Array diff --git a/license/COPYRIGHT.txt b/license/COPYRIGHT.txt new file mode 100644 index 000000000..7bf2faffd --- /dev/null +++ b/license/COPYRIGHT.txt @@ -0,0 +1,15 @@ +/* + * Copyright 2018-2021 KMath contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file diff --git a/license/COPYRIGHT_HEADER.txt b/license/COPYRIGHT_HEADER.txt new file mode 100644 index 000000000..3e7d28489 --- /dev/null +++ b/license/COPYRIGHT_HEADER.txt @@ -0,0 +1,4 @@ +/* + * 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. + */ \ No newline at end of file diff --git a/LICENSE b/license/LICENSE.txt similarity index 99% rename from LICENSE rename to license/LICENSE.txt index 261eeb9e9..84b106a07 100644 --- a/LICENSE +++ b/license/LICENSE.txt @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2018-2021 KMath contributors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/license/README.md b/license/README.md new file mode 100644 index 000000000..6d51e7a05 --- /dev/null +++ b/license/README.md @@ -0,0 +1,17 @@ +The Apache 2 license (given in full in LICENSE.txt) applies to all code in this repository, which is copyright by the +contributors of KMath. The following sections of the repository contain third-party code, to which different licenses +may apply: + +## KMath Libraries + +The following modules contain third-party code and are incorporated into the KMath Libraries: + + - Path: kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt + - License: Apache 2 ([cm](third_party/cm_license.txt)) + - Origin: Derived from Apache Commons Math, (c) 2001-2020 The Apache Software Foundation + - Path: kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt + - License: Apache 2 ([cm](third_party/cm_license.txt)) + - Origin: Derived from Apache Commons Math, (c) 2001-2020 The Apache Software Foundation +- Path: kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LoessInterpolator.kt + - License: Apache 2 ([cm](third_party/cm_license.txt)) + - Origin: Derived from Apache Commons Math, (c) 2001-2020 The Apache Software Foundation diff --git a/license/third_party/cm_license.txt b/license/third_party/cm_license.txt new file mode 100644 index 000000000..6172c3fb2 --- /dev/null +++ b/license/third_party/cm_license.txt @@ -0,0 +1,457 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +Apache Commons Math includes the following code provided to the ASF under the +Apache License 2.0: + + - The inverse error function implementation in the Erf class is based on CUDA + code developed by Mike Giles, Oxford-Man Institute of Quantitative Finance, + and published in GPU Computing Gems, volume 2, 2010 (grant received on + March 23th 2013) + - The LinearConstraint, LinearObjectiveFunction, LinearOptimizer, + RelationShip, SimplexSolver and SimplexTableau classes in package + org.apache.commons.math3.optimization.linear include software developed by + Benjamin McCann (http://www.benmccann.com) and distributed with + the following copyright: Copyright 2009 Google Inc. (grant received on + March 16th 2009) + - The class "org.apache.commons.math3.exception.util.LocalizedFormatsTest" which + is an adapted version of "OrekitMessagesTest" test class for the Orekit library + - The "org.apache.commons.math3.analysis.interpolation.HermiteInterpolator" + has been imported from the Orekit space flight dynamics library. + +=============================================================================== + + + +APACHE COMMONS MATH DERIVATIVE WORKS: + +The Apache commons-math library includes a number of subcomponents +whose implementation is derived from original sources written +in C or Fortran. License terms of the original sources +are reproduced below. + +=============================================================================== +For the lmder, lmpar and qrsolv Fortran routine from minpack and translated in +the LevenbergMarquardtOptimizer class in package +org.apache.commons.math3.optimization.general +Original source copyright and license statement: + +Minpack Copyright Notice (1999) University of Chicago. All rights reserved + +Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain the above +copyright notice, this list of conditions and the following +disclaimer. + +2. Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following +disclaimer in the documentation and/or other materials +provided with the distribution. + +3. The end-user documentation included with the +redistribution, if any, must include the following +acknowledgment: + + "This product includes software developed by the + University of Chicago, as Operator of Argonne National + Laboratory. + +Alternately, this acknowledgment may appear in the software +itself, if and wherever such third-party acknowledgments +normally appear. + +4. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" +WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE +UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND +THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE +OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY +OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR +USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF +THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4) +DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION +UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL +BE CORRECTED. + +5. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT +HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF +ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT, +INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF +ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF +PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER +SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT +(INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE, +EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE +POSSIBILITY OF SUCH LOSS OR DAMAGES. +=============================================================================== + +Copyright and license statement for the odex Fortran routine developed by +E. Hairer and G. Wanner and translated in GraggBulirschStoerIntegrator class +in package org.apache.commons.math3.ode.nonstiff: + + +Copyright (c) 2004, Ernst Hairer + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +=============================================================================== + +Copyright and license statement for the original Mersenne twister C +routines translated in MersenneTwister class in package +org.apache.commons.math3.random: + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================== + +The initial code for shuffling an array (originally in class +"org.apache.commons.math3.random.RandomDataGenerator", now replaced by +a method in class "org.apache.commons.math3.util.MathArrays") was +inspired from the algorithm description provided in +"Algorithms", by Ian Craw and John Pulham (University of Aberdeen 1999). +The textbook (containing a proof that the shuffle is uniformly random) is +available here: + http://citeseerx.ist.psu.edu/viewdoc/download;?doi=10.1.1.173.1898&rep=rep1&type=pdf + +=============================================================================== +License statement for the direction numbers in the resource files for Sobol sequences. + +----------------------------------------------------------------------------- +Licence pertaining to sobol.cc and the accompanying sets of direction numbers + +----------------------------------------------------------------------------- +Copyright (c) 2008, Frances Y. Kuo and Stephen Joe +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the copyright holders nor the names of the + University of New South Wales and the University of Waikato + and its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +=============================================================================== + +The initial commit of package "org.apache.commons.math3.ml.neuralnet" is +an adapted version of code developed in the context of the Data Processing +and Analysis Consortium (DPAC) of the "Gaia" project of the European Space +Agency (ESA). +=============================================================================== + +The initial commit of the class "org.apache.commons.math3.special.BesselJ" is +an adapted version of code translated from the netlib Fortran program, rjbesl +http://www.netlib.org/specfun/rjbesl by R.J. Cody at Argonne National +Laboratory (USA). There is no license or copyright statement included with the +original Fortran sources. +=============================================================================== + + +The BracketFinder (package org.apache.commons.math3.optimization.univariate) +and PowellOptimizer (package org.apache.commons.math3.optimization.general) +classes are based on the Python code in module "optimize.py" (version 0.5) +developed by Travis E. Oliphant for the SciPy library (http://www.scipy.org/) +Copyright © 2003-2009 SciPy Developers. + +SciPy license +Copyright © 2001, 2002 Enthought, Inc. +All rights reserved. + +Copyright © 2003-2013 SciPy Developers. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Enthought nor the names of the SciPy Developers may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +=============================================================================== diff --git a/settings.gradle.kts b/settings.gradle.kts index b4d7b3049..b2bcd9b1d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,8 @@ +/* + * 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. + */ + pluginManagement { repositories { maven("https://repo.kotlin.link") From b7da52edb196769ac5afb42ae5dbdca6bedd58f5 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Thu, 15 Apr 2021 23:10:15 +0300 Subject: [PATCH 203/393] pretty printer --- .../kscience/kmath/tensors/core/utils.kt | 48 +++++++++++++- .../src/jvmMain/kotlin/tensorPrettyPrinter.kt | 64 +++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 392abd1c2..e67591c9e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -1,5 +1,7 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.as1D +import space.kscience.kmath.nd.as2D import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.* @@ -57,4 +59,48 @@ internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { ii } -internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.linearStructure.dim, i) \ No newline at end of file +internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.linearStructure.dim, i) + +public fun DoubleTensor.toPrettyString(): String = buildString { + var offset = 0 + val shape = this@toPrettyString.shape + val linearStructure = this@toPrettyString.linearStructure + var vectorSize = shape.last() + val initString = "DoubleTensor(\n" + append(initString) + var charOffset = 3 + for (vector in vectorSequence()) { + append(" ".repeat(charOffset)) + val index = linearStructure.index(offset) + for (ind in index.reversed()) { + if (ind != 0) { + break + } + append("[") + charOffset += 1 + } + // todo refactor + val values = mutableListOf() + for (i in 0 until vectorSize) { + values.add(vector[intArrayOf(i)]) + } + // todo apply exp formatting + append(values.joinToString(", ")) + append("]") + charOffset -= 1 + for ((ind, maxInd) in index.reversed().zip(shape.reversed()).drop(1)){ + if (ind != maxInd - 1) { + break + } + append("]") + charOffset -=1 + } + offset += vectorSize + // todo refactor + if (this@toPrettyString.numel == offset) { + break + } + append(",\n") + } + append("\n)") +} diff --git a/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt b/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt new file mode 100644 index 000000000..669a5494b --- /dev/null +++ b/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt @@ -0,0 +1,64 @@ + +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.vectorSequence +import java.lang.StringBuilder + +internal fun format(value: Double, digits: Int = 4): String { + val res = "%.${digits}e".format(value).replace(',', '.') + if (value < 0.0) { + return res + } + return StringBuilder().append(" ").append(res).toString() +} + +public fun DoubleTensor.toPrettyString(): String { + val builder = StringBuilder() + with(builder) { + var offset = 0 + val shape = this@toPrettyString.shape + val linearStructure = this@toPrettyString.linearStructure + var vectorSize = shape.last() + val initString = "DoubleTensor(\n" + append(initString) + var charOffset = 3 + for (vector in vectorSequence()) { + append(" ".repeat(charOffset)) + val index = linearStructure.index(offset) + for (ind in index.reversed()) { + if (ind != 0) { + break + } + append("[") + charOffset += 1 + } + // todo refactor + val values = mutableListOf() + for (i in 0 until vectorSize) { + values.add(vector[intArrayOf(i)]) + } + append(values.map { format(it) }.joinToString(", ")) + append("]") + charOffset -= 1 + for (i in shape.size - 2 downTo 0){ + val ind = index[i] + val maxInd = shape[i] + if (ind != maxInd - 1) { + break + } + append("]") + charOffset -=1 + } + offset += vectorSize + // todo refactor + if (this@toPrettyString.numel == offset) { + break + } + append(",\n") + } + append("\n)") + } + return builder.toString() +} + + + From 41ac72b4fbf5527a9a37296da90ff412e66cf542 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 16 Apr 2021 07:45:31 +0100 Subject: [PATCH 204/393] MPP toString for DoubleTensor --- .../kmath/tensors/core/BufferedTensor.kt | 4 ++- .../kscience/kmath/tensors/core/linutils.kt | 4 +-- .../kscience/kmath/tensors/core/utils.kt | 33 ++++++++++++++----- .../src/jvmMain/kotlin/tensorPrettyPrinter.kt | 4 +-- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 9a4d13d2c..9e393f1a8 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -4,7 +4,6 @@ import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.TensorStructure - public open class BufferedTensor( override val shape: IntArray, public val buffer: MutableBuffer, @@ -70,6 +69,9 @@ public class DoubleTensor internal constructor( { internal constructor(bufferedTensor: BufferedTensor): this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) + + override fun toString(): String = toPrettyString() + } internal fun BufferedTensor.asTensor(): IntTensor = IntTensor(this) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index ee159b614..ba5e0caaf 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -190,9 +190,7 @@ internal inline fun choleskyHelper( } } -internal inline fun luMatrixDet(luTensor: MutableStructure2D, pivotsTensor: MutableStructure1D): Double { - val lu = luTensor.as2D() - val pivots = pivotsTensor.as1D() +internal inline fun luMatrixDet(lu: MutableStructure2D, pivots: MutableStructure1D): Double { if (lu[0, 0] == 0.0) { return 0.0 } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index e67591c9e..daab79016 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -1,11 +1,11 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.as1D -import space.kscience.kmath.nd.as2D import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.* -import kotlin.math.sqrt +import kotlin.math.* /** * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. @@ -61,7 +61,25 @@ internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.linearStructure.dim, i) -public fun DoubleTensor.toPrettyString(): String = buildString { +internal inline fun format(value: Double, digits: Int = 4): String { + val ten = 10.0 + val approxOrder = ceil(log10(abs(value))).toInt() + val order = if( + ((value % ten) == 0.0) or + (value == 1.0) or + ((1/value) % ten == 0.0)) approxOrder else approxOrder - 1 + + val lead = value / ten.pow(order) + val leadDisplay = round(lead*ten.pow(digits)) / ten.pow(digits) + val orderDisplay = if(order >= 0) "+$order" else "$order" + val valueDisplay = "${leadDisplay}E$orderDisplay" + val res = if(value < 0.0) valueDisplay else " $valueDisplay" + val fLength = digits + 6 + val endSpace = " ".repeat(fLength - res.length) + return "$res$endSpace" +} + +internal inline fun DoubleTensor.toPrettyString(): String = buildString { var offset = 0 val shape = this@toPrettyString.shape val linearStructure = this@toPrettyString.linearStructure @@ -79,12 +97,9 @@ public fun DoubleTensor.toPrettyString(): String = buildString { append("[") charOffset += 1 } - // todo refactor - val values = mutableListOf() - for (i in 0 until vectorSize) { - values.add(vector[intArrayOf(i)]) - } - // todo apply exp formatting + + val values = vector.as1D().toMutableList().map(::format) + append(values.joinToString(", ")) append("]") charOffset -= 1 diff --git a/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt b/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt index 669a5494b..d3ce5933e 100644 --- a/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt +++ b/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt @@ -2,7 +2,7 @@ import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.vectorSequence import java.lang.StringBuilder - +/* internal fun format(value: Double, digits: Int = 4): String { val res = "%.${digits}e".format(value).replace(',', '.') if (value < 0.0) { @@ -59,6 +59,6 @@ public fun DoubleTensor.toPrettyString(): String { } return builder.toString() } - +*/ From baa303171eb9a6a99b3f5e83cae87a1e0a1abb5f Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 16 Apr 2021 07:47:06 +0100 Subject: [PATCH 205/393] No jvm specifics please --- .../src/jvmMain/kotlin/tensorPrettyPrinter.kt | 64 ------------------- 1 file changed, 64 deletions(-) delete mode 100644 kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt diff --git a/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt b/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt deleted file mode 100644 index d3ce5933e..000000000 --- a/kmath-tensors/src/jvmMain/kotlin/tensorPrettyPrinter.kt +++ /dev/null @@ -1,64 +0,0 @@ - -import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.vectorSequence -import java.lang.StringBuilder -/* -internal fun format(value: Double, digits: Int = 4): String { - val res = "%.${digits}e".format(value).replace(',', '.') - if (value < 0.0) { - return res - } - return StringBuilder().append(" ").append(res).toString() -} - -public fun DoubleTensor.toPrettyString(): String { - val builder = StringBuilder() - with(builder) { - var offset = 0 - val shape = this@toPrettyString.shape - val linearStructure = this@toPrettyString.linearStructure - var vectorSize = shape.last() - val initString = "DoubleTensor(\n" - append(initString) - var charOffset = 3 - for (vector in vectorSequence()) { - append(" ".repeat(charOffset)) - val index = linearStructure.index(offset) - for (ind in index.reversed()) { - if (ind != 0) { - break - } - append("[") - charOffset += 1 - } - // todo refactor - val values = mutableListOf() - for (i in 0 until vectorSize) { - values.add(vector[intArrayOf(i)]) - } - append(values.map { format(it) }.joinToString(", ")) - append("]") - charOffset -= 1 - for (i in shape.size - 2 downTo 0){ - val ind = index[i] - val maxInd = shape[i] - if (ind != maxInd - 1) { - break - } - append("]") - charOffset -=1 - } - offset += vectorSize - // todo refactor - if (this@toPrettyString.numel == offset) { - break - } - append(",\n") - } - append("\n)") - } - return builder.toString() -} -*/ - - From ba3c9b6d45cdb724d8f2e40d8a8e236e4dfd8b48 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 16 Apr 2021 09:47:30 +0300 Subject: [PATCH 206/393] BigIntBenchmarks. cleanup --- examples/build.gradle.kts | 8 +++++ .../kmath/benchmarks/BigIntBenchmark.kt | 32 +++++++++++++++++++ .../kscience/kmath/commons/linear/CMMatrix.kt | 4 +-- .../kmath/structures/NumberNDFieldTest.kt | 2 +- .../space/kscience/kmath/ejml/EjmlMatrix.kt | 2 +- .../kmath/integration/GaussIntegrator.kt | 20 +++++++++++- .../integration/GaussIntegratorRuleFactory.kt | 19 ++++++----- .../histogram/MultivariateHistogramTest.kt | 2 +- .../kscience/kmath/internal/InternalGamma.kt | 2 +- .../kscience/kmath/internal/InternalUtils.kt | 2 +- .../NoDerivFunctionOptimization.kt | 2 +- .../kmath/stat/RandomSourceGenerator.kt | 2 +- .../kscience/kmath/viktor/ViktorBuffer.kt | 2 +- 13 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index d02e5268e..29aa1af6e 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -103,6 +103,14 @@ benchmark { iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds include("MatrixInverseBenchmark") } + + configurations.register("bigInt") { + warmups = 1 // number of warmup iterations + iterations = 3 // number of iterations + iterationTime = 500 // time in seconds per iteration + iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + include("BigIntBenchmark") + } } kotlin.sourceSets.all { diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt new file mode 100644 index 000000000..543d51bee --- /dev/null +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -0,0 +1,32 @@ +package space.kscience.kmath.benchmarks + +import kotlinx.benchmark.Blackhole +import org.openjdk.jmh.annotations.Benchmark +import org.openjdk.jmh.annotations.Scope +import org.openjdk.jmh.annotations.State +import space.kscience.kmath.operations.BigIntField +import space.kscience.kmath.operations.JBigIntegerField +import space.kscience.kmath.operations.invoke + +@State(Scope.Benchmark) +internal class BigIntBenchmark { + @Benchmark + fun kmAdd(blackhole: Blackhole) = BigIntField{ + blackhole.consume(one + number(Int.MAX_VALUE)) + } + + @Benchmark + fun jvmAdd(blackhole: Blackhole) = JBigIntegerField{ + blackhole.consume(one + number(Int.MAX_VALUE)) + } + + @Benchmark + fun kmMultiply(blackhole: Blackhole) = BigIntField{ + blackhole.consume(number(Int.MAX_VALUE)* number(Int.MAX_VALUE)) + } + + @Benchmark + fun jvmMultiply(blackhole: Blackhole) = JBigIntegerField{ + blackhole.consume(number(Int.MAX_VALUE)* number(Int.MAX_VALUE)) + } +} \ No newline at end of file diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index 80929e6b9..99219c19f 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -9,14 +9,14 @@ import space.kscience.kmath.structures.DoubleBuffer import kotlin.reflect.KClass import kotlin.reflect.cast -public inline class CMMatrix(public val origin: RealMatrix) : Matrix { +public class CMMatrix(public val origin: RealMatrix) : Matrix { public override val rowNum: Int get() = origin.rowDimension public override val colNum: Int get() = origin.columnDimension public override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j) } -public inline class CMVector(public val origin: RealVector) : Point { +public class CMVector(public val origin: RealVector) : Point { public override val size: Int get() = origin.dimension public override operator fun get(index: Int): Double = origin.getEntry(index) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt index 376415a56..01fde190f 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt @@ -70,7 +70,7 @@ class NumberNDFieldTest { object L2Norm : Norm, Double> { override fun norm(arg: StructureND): Double = - kotlin.math.sqrt(arg.elements().sumByDouble { it.second.toDouble() }) + kotlin.math.sqrt(arg.elements().sumOf { it.second.toDouble() }) } @Test diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index 10afd6ec2..30b6dc2ee 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.linear.Matrix * @property origin the underlying [SimpleMatrix]. * @author Iaroslav Postovalov */ -public inline class EjmlMatrix(public val origin: SimpleMatrix) : Matrix { +public class EjmlMatrix(public val origin: SimpleMatrix) : Matrix { public override val rowNum: Int get() = origin.numRows() public override val colNum: Int get() = origin.numCols() diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index a4f79f542..9a950e05e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -31,7 +31,7 @@ public class GaussIntegrator> internal constructor( init { require(points.size == weights.size) { "Inconsistent points and weights sizes" } - require(points.indices.all { i -> i == 0 || points[i] > points[i - 1] }){"Integration nodes must be sorted"} + require(points.indices.all { i -> i == 0 || points[i] > points[i - 1] }) { "Integration nodes must be sorted" } } override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand = with(algebra) { @@ -51,6 +51,9 @@ public class GaussIntegrator> internal constructor( public companion object { + /** + * Integrate given [function] in a [range] with Gauss-Legendre quadrature with [numPoints] points. + */ public fun integrate( range: ClosedRange, numPoints: Int = 100, @@ -63,5 +66,20 @@ public class GaussIntegrator> internal constructor( UnivariateIntegrand(function, IntegrationRange(range)) ) } + +// public fun integrate( +// borders: List, +// numPoints: Int = 10, +// ruleFactory: GaussIntegratorRuleFactory = GaussLegendreDoubleRuleFactory, +// features: List = emptyList(), +// function: (Double) -> Double, +// ): UnivariateIntegrand { +// require(borders.indices.all { i -> i == 0 || borders[i] > borders[i - 1] }){"Borders are not sorted"} +// +// val (points, weights) = ruleFactory.build(numPoints, range) +// return GaussIntegrator(DoubleField, points, weights).integrate( +// UnivariateIntegrand(function, IntegrationRange(range)) +// ) +// } } } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt index 678e6bf0a..be7e298af 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt @@ -10,6 +10,7 @@ import kotlin.native.concurrent.ThreadLocal public interface GaussIntegratorRuleFactory { public val algebra: Field public val bufferFactory: BufferFactory + public fun build(numPoints: Int): Pair, Buffer> public companion object { @@ -20,6 +21,7 @@ public interface GaussIntegratorRuleFactory { /** * Create an integration rule by scaling existing normalized rule + * */ public fun > GaussIntegratorRuleFactory.build( numPoints: Int, @@ -45,8 +47,8 @@ public fun > GaussIntegratorRuleFactory.build( /** * Gauss integrator rule based ont Legendre polynomials. All rules are normalized to * - * The code is based on Apache Commons Math source code version 3.6.1 - * https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/analysis/integration/gauss/LegendreRuleFactory.html + * The code is based on [Apache Commons Math source code version 3.6.1](https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/analysis/integration/gauss/LegendreRuleFactory.html) + * */ @ThreadLocal public object GaussLegendreDoubleRuleFactory : GaussIntegratorRuleFactory { @@ -96,12 +98,12 @@ public object GaussLegendreDoubleRuleFactory : GaussIntegratorRuleFactory= -0.5) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt index 832689b27..b0e4ae9f3 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt @@ -21,7 +21,7 @@ internal object InternalUtils { fun validateProbabilities(probabilities: DoubleArray?): Double { require(!(probabilities == null || probabilities.isEmpty())) { "Probabilities must not be empty." } - val sumProb = probabilities.sumByDouble { prob -> + val sumProb = probabilities.sumOf { prob -> require(!(prob < 0 || prob.isInfinite() || prob.isNaN())) { "Invalid probability: $prob" } prob } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt index b8785dd8c..b2ff5aef4 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt @@ -40,7 +40,7 @@ public interface NoDerivFunctionOptimization : Optimization { require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } return Expression { arguments -> - x.indices.sumByDouble { + x.indices.sumOf { val xValue = x[it] val yValue = y[it] val yErrValue = yErr[it] diff --git a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt index f6a5d6605..d72f82ffd 100644 --- a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt +++ b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt @@ -32,7 +32,7 @@ public class RandomSourceGenerator internal constructor(public val source: Rando * * @property generator the underlying [RandomGenerator] object. */ -public inline class RandomGeneratorProvider(public val generator: RandomGenerator) : UniformRandomProvider { +public class RandomGeneratorProvider(public val generator: RandomGenerator) : UniformRandomProvider { /** * Generates a [Boolean] value. * diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt index 1592763db..9d817112d 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt @@ -4,7 +4,7 @@ import org.jetbrains.bio.viktor.F64FlatArray import space.kscience.kmath.structures.MutableBuffer @Suppress("NOTHING_TO_INLINE", "OVERRIDE_BY_INLINE") -public inline class ViktorBuffer(public val flatArray: F64FlatArray) : MutableBuffer { +public class ViktorBuffer(public val flatArray: F64FlatArray) : MutableBuffer { public override val size: Int get() = flatArray.size From 1d1937405d013e09478ec6843d67cb22efef5934 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 16 Apr 2021 10:05:51 +0300 Subject: [PATCH 207/393] BigIntBenchmarks. Rollback to gradle 6.8.3 because incompatibility with benchmarks --- .../kscience/kmath/benchmarks/BigIntBenchmark.kt | 12 ++++++++---- gradle/wrapper/gradle-wrapper.properties | 2 +- .../kotlin/kaceince/kmath/real/GridTest.kt | 2 ++ .../kmath/histogram/MultivariateHistogramTest.kt | 2 +- kmath-viktor/api/kmath-viktor.api | 16 +--------------- settings.gradle.kts | 2 +- 6 files changed, 14 insertions(+), 22 deletions(-) diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index 543d51bee..6c0af40be 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -10,23 +10,27 @@ import space.kscience.kmath.operations.invoke @State(Scope.Benchmark) internal class BigIntBenchmark { + + val kmNumber = BigIntField.number(Int.MAX_VALUE) + val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE) + @Benchmark fun kmAdd(blackhole: Blackhole) = BigIntField{ - blackhole.consume(one + number(Int.MAX_VALUE)) + blackhole.consume(kmNumber + kmNumber + kmNumber) } @Benchmark fun jvmAdd(blackhole: Blackhole) = JBigIntegerField{ - blackhole.consume(one + number(Int.MAX_VALUE)) + blackhole.consume(jvmNumber + jvmNumber+ jvmNumber) } @Benchmark fun kmMultiply(blackhole: Blackhole) = BigIntField{ - blackhole.consume(number(Int.MAX_VALUE)* number(Int.MAX_VALUE)) + blackhole.consume(kmNumber*kmNumber*kmNumber) } @Benchmark fun jvmMultiply(blackhole: Blackhole) = JBigIntegerField{ - blackhole.consume(number(Int.MAX_VALUE)* number(Int.MAX_VALUE)) + blackhole.consume(jvmNumber*jvmNumber*jvmNumber) } } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f371643ee..442d9132e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt index a7c4d30e2..560372952 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/GridTest.kt @@ -1,5 +1,6 @@ package kaceince.kmath.real +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.real.DoubleVector import space.kscience.kmath.real.minus import space.kscience.kmath.real.norm @@ -8,6 +9,7 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue +@UnstableKMathAPI class GridTest { @Test fun testStepGrid() { diff --git a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt index b4a30e2d2..70efffd25 100644 --- a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt @@ -71,7 +71,7 @@ internal class MultivariateHistogramTest { assertTrue { res.bins.count() >= histogram1.bins.count() } - assertEquals(0.0, res.bins.sumByDouble { it.value.toDouble() }) + assertEquals(0.0, res.bins.sumOf { it.value.toDouble() }) } } } \ No newline at end of file diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api index bcfb49e61..87ff6d712 100644 --- a/kmath-viktor/api/kmath-viktor.api +++ b/kmath-viktor/api/kmath-viktor.api @@ -1,27 +1,13 @@ public final class space/kscience/kmath/viktor/ViktorBuffer : space/kscience/kmath/structures/MutableBuffer { - public static final synthetic fun box-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)Lspace/kscience/kmath/viktor/ViktorBuffer; - public static fun constructor-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)Lorg/jetbrains/bio/viktor/F64FlatArray; + public fun (Lorg/jetbrains/bio/viktor/F64FlatArray;)V public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; - public static fun copy-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)Lspace/kscience/kmath/structures/MutableBuffer; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Lorg/jetbrains/bio/viktor/F64FlatArray;Lorg/jetbrains/bio/viktor/F64FlatArray;)Z public fun get (I)Ljava/lang/Double; public synthetic fun get (I)Ljava/lang/Object; - public static fun get-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;I)Ljava/lang/Double; public final fun getFlatArray ()Lorg/jetbrains/bio/viktor/F64FlatArray; public fun getSize ()I - public static fun getSize-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)I - public fun hashCode ()I - public static fun hashCode-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)I public fun iterator ()Ljava/util/Iterator; - public static fun iterator-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)Ljava/util/Iterator; public fun set (ID)V public synthetic fun set (ILjava/lang/Object;)V - public static fun set-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;ID)V - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Lorg/jetbrains/bio/viktor/F64FlatArray;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Lorg/jetbrains/bio/viktor/F64FlatArray; } public final class space/kscience/kmath/viktor/ViktorFieldND : space/kscience/kmath/nd/FieldND, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { diff --git a/settings.gradle.kts b/settings.gradle.kts index 0f281f46c..12a0b11b9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -39,5 +39,5 @@ include( ":kmath-ast", ":kmath-ejml", ":kmath-kotlingrad", - ":examples", + ":examples" ) From 1e7cf39150be8393acd0f24572d0a1a93ef87e15 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 16 Apr 2021 11:58:42 +0100 Subject: [PATCH 208/393] Don't print 0 order --- .../kotlin/space/kscience/kmath/tensors/core/utils.kt | 6 +++--- .../space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index daab79016..40d40b593 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -71,8 +71,8 @@ internal inline fun format(value: Double, digits: Int = 4): String { val lead = value / ten.pow(order) val leadDisplay = round(lead*ten.pow(digits)) / ten.pow(digits) - val orderDisplay = if(order >= 0) "+$order" else "$order" - val valueDisplay = "${leadDisplay}E$orderDisplay" + val orderDisplay = if(order == 0) "" else if(order > 0) "E+$order" else "E$order" + val valueDisplay = "${leadDisplay}$orderDisplay" val res = if(value < 0.0) valueDisplay else " $valueDisplay" val fLength = digits + 6 val endSpace = " ".repeat(fLength - res.length) @@ -83,7 +83,7 @@ internal inline fun DoubleTensor.toPrettyString(): String = buildString { var offset = 0 val shape = this@toPrettyString.shape val linearStructure = this@toPrettyString.linearStructure - var vectorSize = shape.last() + val vectorSize = shape.last() val initString = "DoubleTensor(\n" append(initString) var charOffset = 3 diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 4f4d9bbdf..ddcf0369c 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -46,4 +46,10 @@ class TestDoubleTensor { assertEquals(secondRow[1], secondColumn[1]) } } + + @Test + fun toStringTest() = DoubleTensorAlgebra { + val tensor = randNormal(intArrayOf(2,3)) + println(tensor) + } } \ No newline at end of file From 4f8ab4dd78ea1a9a8925fce8898c33313e6be9ec Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 16 Apr 2021 12:03:27 +0100 Subject: [PATCH 209/393] Ignore print test --- .../kotlin/space/kscience/kmath/tensors/core/utils.kt | 3 +-- .../space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 40d40b593..0b2b5c0df 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -1,6 +1,5 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.as1D import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator @@ -72,7 +71,7 @@ internal inline fun format(value: Double, digits: Int = 4): String { val lead = value / ten.pow(order) val leadDisplay = round(lead*ten.pow(digits)) / ten.pow(digits) val orderDisplay = if(order == 0) "" else if(order > 0) "E+$order" else "E$order" - val valueDisplay = "${leadDisplay}$orderDisplay" + val valueDisplay = "$leadDisplay$orderDisplay" val res = if(value < 0.0) valueDisplay else " $valueDisplay" val fLength = digits + 6 val endSpace = " ".repeat(fLength - res.length) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index ddcf0369c..f950dfce3 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,8 +1,10 @@ package space.kscience.kmath.tensors.core +import kotlinx.coroutines.InternalCoroutinesApi import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray +import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -47,7 +49,7 @@ class TestDoubleTensor { } } - @Test + @Test @Ignore fun toStringTest() = DoubleTensorAlgebra { val tensor = randNormal(intArrayOf(2,3)) println(tensor) From 1582ac2c291ec6d01edbda42f308f869d75f611b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 16 Apr 2021 18:05:01 +0700 Subject: [PATCH 210/393] Fix import --- kmath-geometry/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index 40f2eb533..65db43edf 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity.PROTOTYPE +import ru.mipt.npm.gradle.Maturity plugins { kotlin("multiplatform") From 82d8394a9fd19461e90a331157e5ac4eee705aab Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 16 Apr 2021 12:05:18 +0100 Subject: [PATCH 211/393] remove kolinx import --- .../kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index f950dfce3..fd75f77fe 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,6 +1,5 @@ package space.kscience.kmath.tensors.core -import kotlinx.coroutines.InternalCoroutinesApi import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray From 65a8d8f581f8b9ec6755530f8ff4a00d0124b9df Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 16 Apr 2021 15:50:33 +0300 Subject: [PATCH 212/393] Field element integration --- CHANGELOG.md | 1 + .../kmath/benchmarks/BigIntBenchmark.kt | 14 +-- .../kscience/kmath/functions/integrate.kt | 16 +++ .../kmath/functions/matrixIntegration.kt | 22 ++++ .../kmath/commons/integration/CMIntegrator.kt | 2 +- .../integration/GaussRuleIntegrator.kt | 2 +- kmath-core/api/kmath-core.api | 2 + .../space/kscience/kmath/structures/Buffer.kt | 9 +- kmath-functions/build.gradle.kts | 27 +++-- .../kmath/integration/GaussIntegrator.kt | 105 ++++++++++++------ .../integration/GaussIntegratorRuleFactory.kt | 29 ++++- .../kscience/kmath/integration/Integrand.kt | 4 +- .../kmath/integration/GaussIntegralTest.kt | 4 +- 13 files changed, 172 insertions(+), 65 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt create mode 100644 examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index f7acd08cd..c3bd2641a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - bindSymbolOrNull - Blocking chains and Statistics - Multiplatform integration +- Integration for any Field element ### Changed - Exponential operations merged with hyperbolic functions diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index fec80d31a..672efd5c2 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -20,22 +20,22 @@ internal class BigIntBenchmark { val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE) @Benchmark - fun kmAdd(blackhole: Blackhole) = BigIntField{ + fun kmAdd(blackhole: Blackhole) = BigIntField { blackhole.consume(kmNumber + kmNumber + kmNumber) } @Benchmark - fun jvmAdd(blackhole: Blackhole) = JBigIntegerField{ - blackhole.consume(jvmNumber + jvmNumber+ jvmNumber) + fun jvmAdd(blackhole: Blackhole) = JBigIntegerField { + blackhole.consume(jvmNumber + jvmNumber + jvmNumber) } @Benchmark - fun kmMultiply(blackhole: Blackhole) = BigIntField{ - blackhole.consume(kmNumber*kmNumber*kmNumber) + fun kmMultiply(blackhole: Blackhole) = BigIntField { + blackhole.consume(kmNumber * kmNumber * kmNumber) } @Benchmark - fun jvmMultiply(blackhole: Blackhole) = JBigIntegerField{ - blackhole.consume(jvmNumber*jvmNumber*jvmNumber) + fun jvmMultiply(blackhole: Blackhole) = JBigIntegerField { + blackhole.consume(jvmNumber * jvmNumber * jvmNumber) } } \ No newline at end of file diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt new file mode 100644 index 000000000..761d006d3 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt @@ -0,0 +1,16 @@ +package space.kscience.kmath.functions + +import space.kscience.kmath.integration.GaussIntegrator +import space.kscience.kmath.integration.value +import kotlin.math.pow + +fun main() { + //Define a function + val function: UnivariateFunction = { x -> 3 * x.pow(2) + 2 * x + 1 } + + //get the result of the integration + val result = GaussIntegrator.legendre(0.0..10.0, function = function) + + //the value is nullable because in some cases the integration could not succeed + println(result.value) +} \ No newline at end of file diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt new file mode 100644 index 000000000..5e92ce22a --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt @@ -0,0 +1,22 @@ +package space.kscience.kmath.functions + +import space.kscience.kmath.integration.GaussIntegrator +import space.kscience.kmath.integration.UnivariateIntegrand +import space.kscience.kmath.integration.value +import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.nd.nd +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.invoke + +fun main(): Unit = DoubleField { + nd(2, 2) { + //Define a function in a nd space + val function: UnivariateFunction> = { x -> 3 * x.pow(2) + 2 * x + 1 } + + //get the result of the integration + val result: UnivariateIntegrand> = GaussIntegrator.legendre(this, 0.0..10.0, function = function) + + //the value is nullable because in some cases the integration could not succeed + println(result.value) + } +} \ No newline at end of file diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt index 15a734531..535c6b39e 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt @@ -36,7 +36,7 @@ public class CMIntegrator( IntegrandValue(res) + IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy) + IntegrandRelativeAccuracy(integrator.relativeAccuracy) + - IntegrandCalls(integrator.evaluations + integrand.calls) + IntegrandCallsPerformed(integrator.evaluations + integrand.calls) } diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt index 67d032e8b..071bac315 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt @@ -22,7 +22,7 @@ public class GaussRuleIntegrator( val integrator: GaussIntegrator = getIntegrator(range) //TODO check performance val res: Double = integrator.integrate(integrand.function) - return integrand + IntegrandValue(res) + IntegrandCalls(integrand.calls + numpoints) + return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + numpoints) } private fun getIntegrator(range: ClosedRange): GaussIntegrator { diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index c62abbf12..6b300123c 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -1791,6 +1791,7 @@ public final class space/kscience/kmath/structures/IntBufferKt { } public final class space/kscience/kmath/structures/ListBuffer : space/kscience/kmath/structures/Buffer { + public fun (ILkotlin/jvm/functions/Function1;)V public fun (Ljava/util/List;)V public fun get (I)Ljava/lang/Object; public final fun getList ()Ljava/util/List; @@ -1865,6 +1866,7 @@ public final class space/kscience/kmath/structures/MutableBuffer$Companion { public final class space/kscience/kmath/structures/MutableListBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/MutableListBuffer; + public static fun constructor-impl (ILkotlin/jvm/functions/Function1;)Ljava/util/List; public static fun constructor-impl (Ljava/util/List;)Ljava/util/List; public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; public static fun copy-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/MutableBuffer; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 551602115..d187beab1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -194,6 +194,9 @@ public interface MutableBuffer : Buffer { * @property list The underlying list. */ public class ListBuffer(public val list: List) : Buffer { + + public constructor(size: Int, initializer: (Int) -> T) : this(List(size, initializer)) + override val size: Int get() = list.size override operator fun get(index: Int): T = list[index] @@ -213,8 +216,10 @@ public fun List.asBuffer(): ListBuffer = ListBuffer(this) */ @JvmInline public value class MutableListBuffer(public val list: MutableList) : MutableBuffer { - override val size: Int - get() = list.size + + public constructor(size: Int, initializer: (Int) -> T) : this(MutableList(size, initializer)) + + override val size: Int get() = list.size override operator fun get(index: Int): T = list[index] diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 795137845..ca678bc0e 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -15,16 +15,23 @@ kotlin.sourceSets.commonMain { } readme { - description = "Functions and interpolation" - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + description = "Functions, integration and interpolation" + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) - feature("piecewise", "src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt", "Piecewise functions.") - feature("polynomials", "src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt", "Polynomial functions.") - feature("linear interpolation", - "src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt", - "Linear XY interpolator.") - feature("spline interpolation", - "src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt", - "Cubic spline XY interpolator.") + feature("piecewise", "src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt") { + "Piecewise functions." + } + feature("polynomials", "src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt") { + "Polynomial functions." + } + feature("linear interpolation", "src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt") { + "Linear XY interpolator." + } + feature("spline interpolation", "src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt") { + "Cubic spline XY interpolator." + } + feature("integration") { + "Univariate and multivariate quadratures" + } } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index 9c94fa7bd..c4b9c572f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -4,27 +4,31 @@ */ package space.kscience.kmath.integration +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.indices +import space.kscience.kmath.operations.Field +import space.kscience.kmath.structures.* + /** * A simple one-pass integrator based on Gauss rule */ -public class GaussIntegrator> internal constructor( - public val algebra: Ring, - private val points: Buffer, - private val weights: Buffer, +public class GaussIntegrator( + public val algebra: Field, + public val bufferFactory: BufferFactory, ) : UnivariateIntegrator { - init { - require(points.size == weights.size) { "Inconsistent points and weights sizes" } - require(points.indices.all { i -> i == 0 || points[i] > points[i - 1] }) { "Integration nodes must be sorted" } + private fun buildRule(integrand: UnivariateIntegrand): Pair, Buffer> { + val factory = integrand.getFeature>() + ?: GenericGaussLegendreRuleFactory(algebra, bufferFactory) + val numPoints = integrand.getFeature()?.maxCalls ?: 100 + val range = integrand.getFeature>()?.range ?: 0.0..1.0 + return factory.build(numPoints, range) } override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand = with(algebra) { val f = integrand.function + val (points, weights) = buildRule(integrand) var res = zero var c = zero for (i in points.indices) { @@ -35,40 +39,73 @@ public class GaussIntegrator> internal constructor( c = t - res - y res = t } - return integrand + IntegrandValue(res) + IntegrandCalls(integrand.calls + points.size) + return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + points.size) } public companion object { /** - * Integrate given [function] in a [range] with Gauss-Legendre quadrature with [numPoints] points. + * Integrate [T]-valued univariate function using provided set of [IntegrandFeature] + * Following features are evaluated: + * * [GaussIntegratorRuleFactory] - A factory for computing the Gauss integration rule. By default uses [GenericGaussLegendreRuleFactory] + * * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. + * * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 100 points. + */ + public fun integrate( + algebra: Field, + bufferFactory: BufferFactory = ::ListBuffer, + vararg features: IntegrandFeature, + function: (T) -> T, + ): UnivariateIntegrand = + GaussIntegrator(algebra, bufferFactory).integrate(UnivariateIntegrand(function, *features)) + + /** + * Integrate in real numbers */ public fun integrate( + vararg features: IntegrandFeature, + function: (Double) -> Double, + ): UnivariateIntegrand = integrate(DoubleField, ::DoubleBuffer, features = features, function) + + /** + * Integrate given [function] in a [range] with Gauss-Legendre quadrature with [numPoints] points. + * The [range] is automatically transformed into [T] using [Field.number] + */ + @UnstableKMathAPI + public fun legendre( + algebra: Field, range: ClosedRange, numPoints: Int = 100, - ruleFactory: GaussIntegratorRuleFactory = GaussLegendreDoubleRuleFactory, - features: List = emptyList(), - function: (Double) -> Double, - ): UnivariateIntegrand { - val (points, weights) = ruleFactory.build(numPoints, range) - return GaussIntegrator(DoubleField, points, weights).integrate( - UnivariateIntegrand(function, IntegrationRange(range)) + bufferFactory: BufferFactory = ::ListBuffer, + vararg features: IntegrandFeature, + function: (T) -> T, + ): UnivariateIntegrand = GaussIntegrator(algebra, bufferFactory).integrate( + UnivariateIntegrand( + function, + IntegrationRange(range), + DoubleGaussLegendreRuleFactory, + IntegrandMaxCalls(numPoints), + *features ) - } + ) -// public fun integrate( -// borders: List, -// numPoints: Int = 10, -// ruleFactory: GaussIntegratorRuleFactory = GaussLegendreDoubleRuleFactory, -// features: List = emptyList(), -// function: (Double) -> Double, -// ): UnivariateIntegrand { -// require(borders.indices.all { i -> i == 0 || borders[i] > borders[i - 1] }){"Borders are not sorted"} -// -// val (points, weights) = ruleFactory.build(numPoints, range) -// return GaussIntegrator(DoubleField, points, weights).integrate( -// UnivariateIntegrand(function, IntegrationRange(range)) -// ) -// } + /** + * Integrate given [function] in a [range] with Gauss-Legendre quadrature with [numPoints] points. + */ + @UnstableKMathAPI + public fun legendre( + range: ClosedRange, + numPoints: Int = 100, + vararg features: IntegrandFeature, + function: (Double) -> Double, + ): UnivariateIntegrand = GaussIntegrator(DoubleField, ::DoubleBuffer).integrate( + UnivariateIntegrand( + function, + IntegrationRange(range), + DoubleGaussLegendreRuleFactory, + IntegrandMaxCalls(numPoints), + *features + ) + ) } } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt index 235325dc4..8e961cc62 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt @@ -12,7 +12,7 @@ import kotlin.jvm.Synchronized import kotlin.math.ulp import kotlin.native.concurrent.ThreadLocal -public interface GaussIntegratorRuleFactory { +public interface GaussIntegratorRuleFactory : IntegrandFeature { public val algebra: Field public val bufferFactory: BufferFactory @@ -20,7 +20,7 @@ public interface GaussIntegratorRuleFactory { public companion object { public fun double(numPoints: Int, range: ClosedRange): Pair, Buffer> = - GaussLegendreDoubleRuleFactory.build(numPoints, range) + DoubleGaussLegendreRuleFactory.build(numPoints, range) } } @@ -28,16 +28,16 @@ public interface GaussIntegratorRuleFactory { * Create an integration rule by scaling existing normalized rule * */ -public fun > GaussIntegratorRuleFactory.build( +public fun GaussIntegratorRuleFactory.build( numPoints: Int, - range: ClosedRange, + range: ClosedRange, ): Pair, Buffer> { val normalized = build(numPoints) with(algebra) { val length = range.endInclusive - range.start val points = normalized.first.map(bufferFactory) { - range.start + length / 2 + length * it / 2 + number(range.start + length / 2) + number(length / 2) * it } val weights = normalized.second.map(bufferFactory) { @@ -56,7 +56,7 @@ public fun > GaussIntegratorRuleFactory.build( * */ @ThreadLocal -public object GaussLegendreDoubleRuleFactory : GaussIntegratorRuleFactory { +public object DoubleGaussLegendreRuleFactory : GaussIntegratorRuleFactory { override val algebra: Field get() = DoubleField @@ -173,3 +173,20 @@ public object GaussLegendreDoubleRuleFactory : GaussIntegratorRuleFactory, Buffer> = getOrBuildRule(numPoints) } + +/** + * A generic Gauss-Legendre rule factory that wraps [DoubleGaussLegendreRuleFactory] in a generic way. + */ +public class GenericGaussLegendreRuleFactory( + override val algebra: Field, + override val bufferFactory: BufferFactory, +) : GaussIntegratorRuleFactory { + + override fun build(numPoints: Int): Pair, Buffer> { + val (doublePoints, doubleWeights) = DoubleGaussLegendreRuleFactory.build(numPoints) + + val points = doublePoints.map(bufferFactory) { algebra.number(it) } + val weights = doubleWeights.map(bufferFactory) { algebra.number(it) } + return points to weights + } +} diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt index ef8efb1db..1ff8e422e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt @@ -21,8 +21,8 @@ public class IntegrandRelativeAccuracy(public val accuracy: Double) : IntegrandF public class IntegrandAbsoluteAccuracy(public val accuracy: Double) : IntegrandFeature -public class IntegrandCalls(public val calls: Int) : IntegrandFeature +public class IntegrandCallsPerformed(public val calls: Int) : IntegrandFeature -public val Integrand.calls: Int get() = getFeature()?.calls ?: 0 +public val Integrand.calls: Int get() = getFeature()?.calls ?: 0 public class IntegrandMaxCalls(public val maxCalls: Int) : IntegrandFeature diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 00105c8fb..247318367 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -13,7 +13,7 @@ import kotlin.test.assertEquals class GaussIntegralTest { @Test fun gaussSin() { - val res = GaussIntegrator.integrate(0.0..2 * PI) { x -> + val res = GaussIntegrator.legendre(0.0..2 * PI) { x -> sin(x) } assertEquals(0.0, res.value!!, 1e-4) @@ -21,7 +21,7 @@ class GaussIntegralTest { @Test fun gaussUniform() { - val res = GaussIntegrator.integrate(0.0..100.0,300) { x -> + val res = GaussIntegrator.legendre(0.0..100.0,300) { x -> if(x in 30.0..50.0){ 1.0 } else { From ef1200aad0db776f07d5f6b4c0572d581acd4470 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 16 Apr 2021 16:39:27 +0300 Subject: [PATCH 213/393] Update integration API --- .../kscience/kmath/functions/integrate.kt | 5 +- .../kmath/functions/matrixIntegration.kt | 13 +- .../kmath/integration/GaussIntegrator.kt | 111 ++++++------------ .../integration/GaussIntegratorRuleFactory.kt | 67 ++++------- .../kmath/integration/UnivariateIntegrand.kt | 5 +- .../kmath/integration/GaussIntegralTest.kt | 7 +- 6 files changed, 79 insertions(+), 129 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt index 761d006d3..90542adf4 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt @@ -1,7 +1,8 @@ package space.kscience.kmath.functions -import space.kscience.kmath.integration.GaussIntegrator +import space.kscience.kmath.integration.integrate import space.kscience.kmath.integration.value +import space.kscience.kmath.operations.DoubleField import kotlin.math.pow fun main() { @@ -9,7 +10,7 @@ fun main() { val function: UnivariateFunction = { x -> 3 * x.pow(2) + 2 * x + 1 } //get the result of the integration - val result = GaussIntegrator.legendre(0.0..10.0, function = function) + val result = DoubleField.integrate(0.0..10.0, function = function) //the value is nullable because in some cases the integration could not succeed println(result.value) diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt index 5e92ce22a..bd431c22c 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt @@ -1,7 +1,6 @@ package space.kscience.kmath.functions -import space.kscience.kmath.integration.GaussIntegrator -import space.kscience.kmath.integration.UnivariateIntegrand +import space.kscience.kmath.integration.integrate import space.kscience.kmath.integration.value import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.nd @@ -10,11 +9,17 @@ import space.kscience.kmath.operations.invoke fun main(): Unit = DoubleField { nd(2, 2) { + + //Produce a diagonal StructureND + fun diagonal(v: Double) = produce { (i, j) -> + if (i == j) v else 0.0 + } + //Define a function in a nd space - val function: UnivariateFunction> = { x -> 3 * x.pow(2) + 2 * x + 1 } + val function: (Double) -> StructureND = { x: Double -> 3 * number(x).pow(2) + 2 * diagonal(x) + 1 } //get the result of the integration - val result: UnivariateIntegrand> = GaussIntegrator.legendre(this, 0.0..10.0, function = function) + val result = integrate(0.0..10.0, function = function) //the value is nullable because in some cases the integration could not succeed println(result.value) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index c4b9c572f..bc23e2f1b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.integration import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Field import space.kscience.kmath.structures.* @@ -15,12 +14,10 @@ import space.kscience.kmath.structures.* */ public class GaussIntegrator( public val algebra: Field, - public val bufferFactory: BufferFactory, ) : UnivariateIntegrator { - private fun buildRule(integrand: UnivariateIntegrand): Pair, Buffer> { - val factory = integrand.getFeature>() - ?: GenericGaussLegendreRuleFactory(algebra, bufferFactory) + private fun buildRule(integrand: UnivariateIntegrand): Pair, Buffer> { + val factory = integrand.getFeature() ?: GaussLegendreRuleFactory val numPoints = integrand.getFeature()?.maxCalls ?: 100 val range = integrand.getFeature>()?.range ?: 0.0..1.0 return factory.build(numPoints, range) @@ -32,9 +29,9 @@ public class GaussIntegrator( var res = zero var c = zero for (i in points.indices) { - val x: T = points[i] - val w: T = weights[i] - val y: T = w * f(x) - c + val x = points[i] + val weight = weights[i] + val y: T = weight * f(x) - c val t = res + y c = t - res - y res = t @@ -44,68 +41,38 @@ public class GaussIntegrator( public companion object { - /** - * Integrate [T]-valued univariate function using provided set of [IntegrandFeature] - * Following features are evaluated: - * * [GaussIntegratorRuleFactory] - A factory for computing the Gauss integration rule. By default uses [GenericGaussLegendreRuleFactory] - * * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. - * * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 100 points. - */ - public fun integrate( - algebra: Field, - bufferFactory: BufferFactory = ::ListBuffer, - vararg features: IntegrandFeature, - function: (T) -> T, - ): UnivariateIntegrand = - GaussIntegrator(algebra, bufferFactory).integrate(UnivariateIntegrand(function, *features)) - - /** - * Integrate in real numbers - */ - public fun integrate( - vararg features: IntegrandFeature, - function: (Double) -> Double, - ): UnivariateIntegrand = integrate(DoubleField, ::DoubleBuffer, features = features, function) - - /** - * Integrate given [function] in a [range] with Gauss-Legendre quadrature with [numPoints] points. - * The [range] is automatically transformed into [T] using [Field.number] - */ - @UnstableKMathAPI - public fun legendre( - algebra: Field, - range: ClosedRange, - numPoints: Int = 100, - bufferFactory: BufferFactory = ::ListBuffer, - vararg features: IntegrandFeature, - function: (T) -> T, - ): UnivariateIntegrand = GaussIntegrator(algebra, bufferFactory).integrate( - UnivariateIntegrand( - function, - IntegrationRange(range), - DoubleGaussLegendreRuleFactory, - IntegrandMaxCalls(numPoints), - *features - ) - ) - - /** - * Integrate given [function] in a [range] with Gauss-Legendre quadrature with [numPoints] points. - */ - @UnstableKMathAPI - public fun legendre( - range: ClosedRange, - numPoints: Int = 100, - vararg features: IntegrandFeature, - function: (Double) -> Double, - ): UnivariateIntegrand = GaussIntegrator(DoubleField, ::DoubleBuffer).integrate( - UnivariateIntegrand( - function, - IntegrationRange(range), - DoubleGaussLegendreRuleFactory, - IntegrandMaxCalls(numPoints), - *features - ) - ) } -} \ No newline at end of file +} + +/** + * Integrate [T]-valued univariate function using provided set of [IntegrandFeature] + * Following features are evaluated: + * * [GaussIntegratorRuleFactory] - A factory for computing the Gauss integration rule. By default uses [GaussLegendreRuleFactory] + * * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. + * * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 100 points. + */ +@UnstableKMathAPI +public fun Field.integrate( + vararg features: IntegrandFeature, + function: (Double) -> T, +): UnivariateIntegrand = GaussIntegrator(this).integrate(UnivariateIntegrand(function, *features)) + + +/** + * Use [GaussIntegrator.Companion.integrate] to integrate the function in the current algebra with given [range] and [numPoints] + */ +@UnstableKMathAPI +public fun Field.integrate( + range: ClosedRange, + numPoints: Int = 100, + vararg features: IntegrandFeature, + function: (Double) -> T, +): UnivariateIntegrand = GaussIntegrator(this).integrate( + UnivariateIntegrand( + function, + IntegrationRange(range), + GaussLegendreRuleFactory, + IntegrandMaxCalls(numPoints), + *features + ) +) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt index 8e961cc62..133f829e3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt @@ -5,22 +5,20 @@ package space.kscience.kmath.integration -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.Field -import space.kscience.kmath.structures.* +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.map import kotlin.jvm.Synchronized import kotlin.math.ulp import kotlin.native.concurrent.ThreadLocal -public interface GaussIntegratorRuleFactory : IntegrandFeature { - public val algebra: Field - public val bufferFactory: BufferFactory - - public fun build(numPoints: Int): Pair, Buffer> +public interface GaussIntegratorRuleFactory : IntegrandFeature { + public fun build(numPoints: Int): Pair, Buffer> public companion object { public fun double(numPoints: Int, range: ClosedRange): Pair, Buffer> = - DoubleGaussLegendreRuleFactory.build(numPoints, range) + GaussLegendreRuleFactory.build(numPoints, range) } } @@ -28,24 +26,23 @@ public interface GaussIntegratorRuleFactory : IntegrandFeature { * Create an integration rule by scaling existing normalized rule * */ -public fun GaussIntegratorRuleFactory.build( +public fun GaussIntegratorRuleFactory.build( numPoints: Int, range: ClosedRange, -): Pair, Buffer> { +): Pair, Buffer> { val normalized = build(numPoints) - with(algebra) { - val length = range.endInclusive - range.start + val length = range.endInclusive - range.start - val points = normalized.first.map(bufferFactory) { - number(range.start + length / 2) + number(length / 2) * it - } - - val weights = normalized.second.map(bufferFactory) { - it * length / 2 - } - - return points to weights + val points = normalized.first.map(::DoubleBuffer) { + range.start + length / 2 + length / 2 * it } + + val weights = normalized.second.map(::DoubleBuffer) { + it * length / 2 + } + + return points to weights + } @@ -56,11 +53,7 @@ public fun GaussIntegratorRuleFactory.build( * */ @ThreadLocal -public object DoubleGaussLegendreRuleFactory : GaussIntegratorRuleFactory { - - override val algebra: Field get() = DoubleField - - override val bufferFactory: BufferFactory get() = ::DoubleBuffer +public object GaussLegendreRuleFactory : GaussIntegratorRuleFactory { private val cache = HashMap, Buffer>>() @@ -171,22 +164,4 @@ public object DoubleGaussLegendreRuleFactory : GaussIntegratorRuleFactory, Buffer> = getOrBuildRule(numPoints) -} - - -/** - * A generic Gauss-Legendre rule factory that wraps [DoubleGaussLegendreRuleFactory] in a generic way. - */ -public class GenericGaussLegendreRuleFactory( - override val algebra: Field, - override val bufferFactory: BufferFactory, -) : GaussIntegratorRuleFactory { - - override fun build(numPoints: Int): Pair, Buffer> { - val (doublePoints, doubleWeights) = DoubleGaussLegendreRuleFactory.build(numPoints) - - val points = doublePoints.map(bufferFactory) { algebra.number(it) } - val weights = doubleWeights.map(bufferFactory) { algebra.number(it) } - return points to weights - } -} +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index e49e83845..0b41a3f8b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -5,14 +5,13 @@ package space.kscience.kmath.integration -import space.kscience.kmath.functions.UnivariateFunction import space.kscience.kmath.misc.UnstableKMathAPI import kotlin.jvm.JvmInline import kotlin.reflect.KClass public class UnivariateIntegrand internal constructor( private val features: Map, IntegrandFeature>, - public val function: UnivariateFunction, + public val function: (Double) -> T, ) : Integrand { @Suppress("UNCHECKED_CAST") @@ -27,7 +26,7 @@ public class UnivariateIntegrand internal constructor( @Suppress("FunctionName") public fun UnivariateIntegrand( - function: (T) -> T, + function: (Double) -> T, vararg features: IntegrandFeature, ): UnivariateIntegrand = UnivariateIntegrand(features.associateBy { it::class }, function) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 247318367..5ec90f42a 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -5,15 +5,18 @@ package space.kscience.kmath.integration +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.DoubleField import kotlin.math.PI import kotlin.math.sin import kotlin.test.Test import kotlin.test.assertEquals +@OptIn(UnstableKMathAPI::class) class GaussIntegralTest { @Test fun gaussSin() { - val res = GaussIntegrator.legendre(0.0..2 * PI) { x -> + val res = DoubleField.integrate(0.0..2 * PI) { x -> sin(x) } assertEquals(0.0, res.value!!, 1e-4) @@ -21,7 +24,7 @@ class GaussIntegralTest { @Test fun gaussUniform() { - val res = GaussIntegrator.legendre(0.0..100.0,300) { x -> + val res = DoubleField.integrate(0.0..100.0,300) { x -> if(x in 30.0..50.0){ 1.0 } else { From e38685951ca3d94836e20590ab2109fa01ffca3a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 16 Apr 2021 19:20:50 +0300 Subject: [PATCH 214/393] Remove unnecessary inlines --- .../space/kscience/kmath/ejml/EjmlVector.kt | 2 +- kmath-viktor/api/kmath-viktor.api | 61 ++++++++----------- .../kmath/viktor/ViktorStructureND.kt | 2 +- 3 files changed, 26 insertions(+), 39 deletions(-) diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt index eb248c9fa..2f4b4a8e2 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt @@ -14,7 +14,7 @@ import space.kscience.kmath.linear.Point * @property origin the underlying [SimpleMatrix]. * @author Iaroslav Postovalov */ -public inline class EjmlVector internal constructor(public val origin: SimpleMatrix) : Point { +public class EjmlVector internal constructor(public val origin: SimpleMatrix) : Point { public override val size: Int get() = origin.numRows() diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api index 87ff6d712..59882627b 100644 --- a/kmath-viktor/api/kmath-viktor.api +++ b/kmath-viktor/api/kmath-viktor.api @@ -13,84 +13,71 @@ public final class space/kscience/kmath/viktor/ViktorBuffer : space/kscience/kma public final class space/kscience/kmath/viktor/ViktorFieldND : space/kscience/kmath/nd/FieldND, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/ScaleOperations { public fun ([I)V public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; - public fun acos-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; + public fun acos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public synthetic fun add (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; - public fun add-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; + public fun add (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; - public fun asin-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; + public fun asin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; - public fun atan-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; + public fun atan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; - public fun combine-WKhNzhk (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array; + public fun combine (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; - public fun cos-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; + public fun cos (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; - public fun exp-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; + public fun exp (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun getElementContext ()Lspace/kscience/kmath/operations/Algebra; public fun getElementContext ()Lspace/kscience/kmath/operations/DoubleField; public final fun getF64Buffer (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; public synthetic fun getOne ()Ljava/lang/Object; - public fun getOne-6kW2wQc ()Lorg/jetbrains/bio/viktor/F64Array; + public fun getOne ()Lspace/kscience/kmath/viktor/ViktorStructureND; public fun getShape ()[I public synthetic fun getZero ()Ljava/lang/Object; - public fun getZero-6kW2wQc ()Lorg/jetbrains/bio/viktor/F64Array; + public fun getZero ()Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; - public fun ln-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; + public fun ln (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; - public fun map-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/bio/viktor/F64Array; + public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; - public fun mapIndexed-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lorg/jetbrains/bio/viktor/F64Array; + public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; + public fun minus (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun number-8UOKELU (Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; - public fun plus-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;D)Lorg/jetbrains/bio/viktor/F64Array; - public fun plus-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; + public fun plus (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun power-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; + public fun power (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; - public fun produce-8UOKELU (Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/bio/viktor/F64Array; + public fun produce (Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; - public fun scale-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;D)Lorg/jetbrains/bio/viktor/F64Array; + public fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; - public fun sin-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; + public fun sin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; - public fun tan-8UOKELU (Lspace/kscience/kmath/nd/StructureND;)Lorg/jetbrains/bio/viktor/F64Array; + public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun times-zrEAbyI (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lorg/jetbrains/bio/viktor/F64Array; + public fun times (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; } public final class space/kscience/kmath/viktor/ViktorStructureND : space/kscience/kmath/nd/MutableStructureND { - public static final synthetic fun box-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lspace/kscience/kmath/viktor/ViktorStructureND; - public static fun constructor-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lorg/jetbrains/bio/viktor/F64Array; + public fun (Lorg/jetbrains/bio/viktor/F64Array;)V public fun elements ()Lkotlin/sequences/Sequence; - public static fun elements-impl (Lorg/jetbrains/bio/viktor/F64Array;)Lkotlin/sequences/Sequence; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Lorg/jetbrains/bio/viktor/F64Array;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Lorg/jetbrains/bio/viktor/F64Array;Lorg/jetbrains/bio/viktor/F64Array;)Z public fun get ([I)Ljava/lang/Double; public synthetic fun get ([I)Ljava/lang/Object; - public static fun get-impl (Lorg/jetbrains/bio/viktor/F64Array;[I)Ljava/lang/Double; public final fun getF64Buffer ()Lorg/jetbrains/bio/viktor/F64Array; public fun getShape ()[I - public static fun getShape-impl (Lorg/jetbrains/bio/viktor/F64Array;)[I - public fun hashCode ()I - public static fun hashCode-impl (Lorg/jetbrains/bio/viktor/F64Array;)I public fun set ([ID)V public synthetic fun set ([ILjava/lang/Object;)V - public static fun set-impl (Lorg/jetbrains/bio/viktor/F64Array;[ID)V - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Lorg/jetbrains/bio/viktor/F64Array;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Lorg/jetbrains/bio/viktor/F64Array; } public final class space/kscience/kmath/viktor/ViktorStructureNDKt { public static final fun ViktorNDField ([I)Lspace/kscience/kmath/viktor/ViktorFieldND; - public static final fun asStructure (Lorg/jetbrains/bio/viktor/F64Array;)Lorg/jetbrains/bio/viktor/F64Array; + public static final fun asStructure (Lorg/jetbrains/bio/viktor/F64Array;)Lspace/kscience/kmath/viktor/ViktorStructureND; } diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt index 72f56d821..dc1b45f5d 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt @@ -14,7 +14,7 @@ import space.kscience.kmath.operations.NumbersAddOperations import space.kscience.kmath.operations.ScaleOperations @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public inline class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructureND { +public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructureND { public override val shape: IntArray get() = f64Buffer.shape public override inline fun get(index: IntArray): Double = f64Buffer.get(*index) From 299592ed25bb4b597a802f031abcc4a7f8cc7917 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 16 Apr 2021 19:44:51 +0300 Subject: [PATCH 215/393] Update readme --- README.md | 27 ++++++++++++++---------- docs/templates/README-TEMPLATE.md | 4 ++++ gradle/wrapper/gradle-wrapper.properties | 5 ----- kmath-ast/README.md | 14 ++++++------ kmath-complex/README.md | 6 +++--- kmath-core/README.md | 6 +++--- kmath-ejml/README.md | 6 +++--- kmath-for-real/README.md | 6 +++--- kmath-functions/README.md | 15 +++++++------ kmath-nd4j/README.md | 6 +++--- 10 files changed, 50 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 71df233b0..0210b4caf 100644 --- a/README.md +++ b/README.md @@ -89,9 +89,9 @@ KMath is a modular library. Different modules provide different features with di > > **Features:** > - [expression-language](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser -> - [mst](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation -> - [mst-building](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt) : MST building algebraic structure -> - [mst-interpreter](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt) : MST interpreter +> - [mst](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation +> - [mst-building](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure +> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter > - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler > - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler @@ -171,15 +171,16 @@ One can still use generic algebras though.
* ### [kmath-functions](kmath-functions) -> Functions and interpolation +> Functions, integration and interpolation > -> **Maturity**: PROTOTYPE +> **Maturity**: EXPERIMENTAL > > **Features:** -> - [piecewise](kmath-functions/Piecewise functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt -> - [polynomials](kmath-functions/Polynomial functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt -> - [linear interpolation](kmath-functions/Linear XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt -> - [spline interpolation](kmath-functions/Cubic spline XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +> - [piecewise](kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt) : Piecewise functions. +> - [polynomials](kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt) : Polynomial functions. +> - [linear interpolation](kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt) : Linear XY interpolator. +> - [spline interpolation](kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt) : Cubic spline XY interpolator. +> - [integration](kmath-functions/#) : Univariate and multivariate quadratures
@@ -250,6 +251,10 @@ cases. We expect the worst KMath benchmarks will perform better than native Pyth native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy. +## Requirements + +KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for execution in order to get better performance. + ### Repositories Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of @@ -261,8 +266,8 @@ repositories { } dependencies { - api("space.kscience:kmath-core:0.3.0-dev-4") - // api("space.kscience.kmath:kmath-core-jvm:0.3.0-dev-4") for jvm-specific version + api("space.kscience:kmath-core:0.3.0-dev-6") + // api("space.kscience:kmath-core-jvm:0.3.0-dev-6") for jvm-specific version } ``` diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index 9e51fcbe8..99951b4d6 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -94,6 +94,10 @@ cases. We expect the worst KMath benchmarks will perform better than native Pyth native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy. +## Requirements + +KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for execution in order to get better performance. + ### Repositories Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2059e8ea0..442d9132e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,8 +1,3 @@ -# -# 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. -# - distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 547775efc..b1ef9c7d3 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -3,16 +3,16 @@ Abstract syntax tree expression representation and related optimizations. - [expression-language](src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser - - [mst](../kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation - - [mst-building](../kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt) : MST building algebraic structure - - [mst-interpreter](../kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt) : MST interpreter + - [mst](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation + - [mst-building](src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure + - [mst-interpreter](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter - [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler - [mst-js-codegen](src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-4`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-6`. **Gradle:** ```gradle @@ -23,7 +23,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0-dev-4' + implementation 'space.kscience:kmath-ast:0.3.0-dev-6' } ``` **Gradle Kotlin DSL:** @@ -35,7 +35,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0-dev-4") + implementation("space.kscience:kmath-ast:0.3.0-dev-6") } ``` @@ -52,7 +52,7 @@ For example, the following builder: DoubleField.mstInField { symbol("x") + 2 }.compile() ``` -… leads to generation of bytecode, which can be decompiled to the following Java class: +… leads to generation of bytecode, which can be decompiled to the following Java class: ```java package space.kscience.kmath.asm.generated; diff --git a/kmath-complex/README.md b/kmath-complex/README.md index ec5bf289f..3a05c3d6d 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-4`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-6`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0-dev-4' + implementation 'space.kscience:kmath-complex:0.3.0-dev-6' } ``` **Gradle Kotlin DSL:** @@ -31,6 +31,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0-dev-4") + implementation("space.kscience:kmath-complex:0.3.0-dev-6") } ``` diff --git a/kmath-core/README.md b/kmath-core/README.md index 5e4f1765d..b83fb13d0 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-4`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-6`. **Gradle:** ```gradle @@ -26,7 +26,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0-dev-4' + implementation 'space.kscience:kmath-core:0.3.0-dev-6' } ``` **Gradle Kotlin DSL:** @@ -38,6 +38,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0-dev-4") + implementation("space.kscience:kmath-core:0.3.0-dev-6") } ``` diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index 1f13a03c5..cae11724d 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-4`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-6`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0-dev-4' + implementation 'space.kscience:kmath-ejml:0.3.0-dev-6' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0-dev-4") + implementation("space.kscience:kmath-ejml:0.3.0-dev-6") } ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index f9c6ed3a0..922e6572b 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-4`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-6`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0-dev-4' + implementation 'space.kscience:kmath-for-real:0.3.0-dev-6' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0-dev-4") + implementation("space.kscience:kmath-for-real:0.3.0-dev-6") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 1e4b06e0f..eef677565 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -2,15 +2,16 @@ Functions and interpolations. - - [piecewise](Piecewise functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt - - [polynomials](Polynomial functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt - - [linear interpolation](Linear XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt - - [spline interpolation](Cubic spline XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt + - [piecewise](src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt) : Piecewise functions. + - [polynomials](src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt) : Polynomial functions. + - [linear interpolation](src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt) : Linear XY interpolator. + - [spline interpolation](src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt) : Cubic spline XY interpolator. + - [integration](#) : Univariate and multivariate quadratures ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-4`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-6`. **Gradle:** ```gradle @@ -21,7 +22,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0-dev-4' + implementation 'space.kscience:kmath-functions:0.3.0-dev-6' } ``` **Gradle Kotlin DSL:** @@ -33,6 +34,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0-dev-4") + implementation("space.kscience:kmath-functions:0.3.0-dev-6") } ``` diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index c8944f1ab..829fe4142 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-4`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-6`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0-dev-4' + implementation 'space.kscience:kmath-nd4j:0.3.0-dev-6' } ``` **Gradle Kotlin DSL:** @@ -32,7 +32,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0-dev-4") + implementation("space.kscience:kmath-nd4j:0.3.0-dev-6") } ``` From 2ac55e851f7c9d7156eb10de49abf83d1ec352fd Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 16 Apr 2021 20:03:44 +0300 Subject: [PATCH 216/393] Update pages.yml remove caches from build pages --- .github/workflows/pages.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 82b0fb303..110537a10 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -15,20 +15,6 @@ jobs: uses: actions/setup-java@v1 with: java-version: 11 - - name: Cache gradle - uses: actions/cache@v2 - with: - path: ~/.gradle/caches - key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }} - restore-keys: | - ubuntu-20.04-gradle- - - name: Cache konan - uses: actions/cache@v2 - with: - path: ~/.konan - key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} - restore-keys: | - ${{ runner.os }}-gradle- - name: Build run: | ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace From 00a2ce2152a5b339b874f9476879e3e6001177cc Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 16 Apr 2021 20:30:40 +0300 Subject: [PATCH 217/393] Back to gradle 7 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 442d9132e..f371643ee 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From a110dc20d5acf61c40596e98bf7ea3b9b9d0ba66 Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Fri, 16 Apr 2021 22:15:12 +0300 Subject: [PATCH 218/393] Tests for large BigIntegers multiplication and power are provided. Km implementation is very slow. --- .../kmath/benchmarks/BigIntBenchmark.kt | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index 672efd5c2..31fafaf75 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -5,19 +5,24 @@ package space.kscience.kmath.benchmarks +import edu.mcgill.kaliningraph.power import kotlinx.benchmark.Blackhole import org.openjdk.jmh.annotations.Benchmark import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State -import space.kscience.kmath.operations.BigIntField -import space.kscience.kmath.operations.JBigIntegerField -import space.kscience.kmath.operations.invoke +import space.kscience.kmath.operations.* @State(Scope.Benchmark) internal class BigIntBenchmark { val kmNumber = BigIntField.number(Int.MAX_VALUE) + val largeKmNumber = BigIntField { + fun BigInt.pow10(): BigInt = power(10, ::multiply) + number(11).pow10().pow10().pow10() + } val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE) + val largeJvmNumber = JBigIntegerField { number(11).pow(1000) } + val bigExponent = 50_000 @Benchmark fun kmAdd(blackhole: Blackhole) = BigIntField { @@ -34,8 +39,28 @@ internal class BigIntBenchmark { blackhole.consume(kmNumber * kmNumber * kmNumber) } + @Benchmark + fun kmMultiplyLarge(blackhole: Blackhole) = BigIntField { + blackhole.consume(largeKmNumber.let { it * it }) + } + @Benchmark fun jvmMultiply(blackhole: Blackhole) = JBigIntegerField { blackhole.consume(jvmNumber * jvmNumber * jvmNumber) } + + @Benchmark + fun jvmMultiplyLarge(blackhole: Blackhole) = JBigIntegerField { + blackhole.consume(largeJvmNumber.let { it * it }) + } + + @Benchmark + fun kmPower(blackhole: Blackhole) = BigIntField { + blackhole.consume(kmNumber.power(bigExponent, ::multiply)) + } + + @Benchmark + fun jvmPower(blackhole: Blackhole) = JBigIntegerField { + blackhole.consume(jvmNumber.pow(bigExponent)) + } } \ No newline at end of file From 8689d29e4c0ee463c907a190125790e00c51444e Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 16 Apr 2021 22:43:10 +0300 Subject: [PATCH 219/393] Fix benchmarks --- .idea/copyright/kmath.xml | 6 - .idea/copyright/profiles_settings.xml | 7 - CHANGELOG.md | 1 + benchmarks/build.gradle.kts | 147 ++++++++++++++++++ .../kmath/benchmarks/ArrayBenchmark.kt | 0 .../kmath/benchmarks/BigIntBenchmark.kt | 0 .../kmath/benchmarks/BufferBenchmark.kt | 0 .../kscience/kmath/benchmarks/DotBenchmark.kt | 0 .../ExpressionsInterpretersBenchmark.kt | 0 .../benchmarks/MatrixInverseBenchmark.kt | 0 .../kmath/benchmarks/NDFieldBenchmark.kt | 0 .../kmath/benchmarks/ViktorBenchmark.kt | 0 .../kmath/benchmarks/ViktorLogBenchmark.kt | 0 build.gradle.kts | 2 +- examples/build.gradle.kts | 67 +------- .../kmath/commons/fit/fitWithAutoDiff.kt | 6 +- kmath-complex/build.gradle.kts | 4 - kmath-dimensions/build.gradle.kts | 5 - kmath-ejml/build.gradle.kts | 9 +- kmath-for-real/build.gradle.kts | 9 +- settings.gradle.kts | 3 +- 21 files changed, 158 insertions(+), 108 deletions(-) delete mode 100644 .idea/copyright/kmath.xml delete mode 100644 .idea/copyright/profiles_settings.xml create mode 100644 benchmarks/build.gradle.kts rename {examples/src/benchmarks => benchmarks/src/jvmMain}/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt (100%) rename {examples/src/benchmarks => benchmarks/src/jvmMain}/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt (100%) rename {examples/src/benchmarks => benchmarks/src/jvmMain}/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt (100%) rename {examples/src/benchmarks => benchmarks/src/jvmMain}/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt (100%) rename {examples/src/benchmarks => benchmarks/src/jvmMain}/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt (100%) rename {examples/src/benchmarks => benchmarks/src/jvmMain}/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt (100%) rename {examples/src/benchmarks => benchmarks/src/jvmMain}/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt (100%) rename {examples/src/benchmarks => benchmarks/src/jvmMain}/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt (100%) rename {examples/src/benchmarks => benchmarks/src/jvmMain}/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt (100%) diff --git a/.idea/copyright/kmath.xml b/.idea/copyright/kmath.xml deleted file mode 100644 index 6fe438777..000000000 --- a/.idea/copyright/kmath.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index 6cc25cb4a..000000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c3bd2641a..f1d33a75a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - Redesign advanced Chain API - Redesign MST. Remove MSTExpression. - Move MST to core +- Separated benchmarks and examples ### Deprecated diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts new file mode 100644 index 000000000..f8e85395b --- /dev/null +++ b/benchmarks/build.gradle.kts @@ -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. + */ + +import ru.mipt.npm.gradle.Maturity + +plugins { + kotlin("multiplatform") + kotlin("plugin.allopen") + id("org.jetbrains.kotlinx.benchmark") +} + +allOpen.annotation("org.openjdk.jmh.annotations.State") +sourceSets.register("benchmarks") + + + +repositories { + mavenCentral() + jcenter() + maven("https://repo.kotlin.link") + maven("https://clojars.org/repo") + maven("https://dl.bintray.com/egor-bogomolov/astminer/") + maven("https://dl.bintray.com/hotkeytlt/maven") + maven("https://jitpack.io") + maven { + setUrl("http://logicrunch.research.it.uu.se/maven/") + isAllowInsecureProtocol = true + } +} + +kotlin { + jvm() + + sourceSets { + val commonMain by getting { + dependencies { + implementation(project(":kmath-ast")) + implementation(project(":kmath-core")) + implementation(project(":kmath-coroutines")) + implementation(project(":kmath-complex")) + implementation(project(":kmath-stat")) + implementation(project(":kmath-dimensions")) + implementation(project(":kmath-for-real")) + implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.0") + } + } + + val jvmMain by getting { + dependencies { + implementation(project(":kmath-commons")) + implementation(project(":kmath-ejml")) + implementation(project(":kmath-nd4j")) + implementation(project(":kmath-kotlingrad")) + implementation(project(":kmath-viktor")) + implementation("org.nd4j:nd4j-native:1.0.0-beta7") + + // uncomment if your system supports AVX2 + // val os = System.getProperty("os.name") + // + // if (System.getProperty("os.arch") in arrayOf("x86_64", "amd64")) when { + // os.startsWith("Windows") -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:windows-x86_64-avx2") + // os == "Linux" -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:linux-x86_64-avx2") + // os == "Mac OS X" -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:macosx-x86_64-avx2") + // } else + // implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") + } + } + } +} + +// Configure benchmark +benchmark { + // Setup configurations + targets { + register("jvm") + } + + configurations.register("buffer") { + warmups = 1 // number of warmup iterations + iterations = 3 // number of iterations + iterationTime = 500 // time in seconds per iteration + iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + include("BufferBenchmark") + } + + configurations.register("dot") { + warmups = 1 // number of warmup iterations + iterations = 3 // number of iterations + iterationTime = 500 // time in seconds per iteration + iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + include("DotBenchmark") + } + + configurations.register("expressions") { + warmups = 1 // number of warmup iterations + iterations = 3 // number of iterations + iterationTime = 500 // time in seconds per iteration + iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + include("ExpressionsInterpretersBenchmark") + } + + configurations.register("matrixInverse") { + warmups = 1 // number of warmup iterations + iterations = 3 // number of iterations + iterationTime = 500 // time in seconds per iteration + iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + include("MatrixInverseBenchmark") + } + + configurations.register("bigInt") { + warmups = 1 // number of warmup iterations + iterations = 3 // number of iterations + iterationTime = 500 // time in seconds per iteration + iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + include("BigIntBenchmark") + } +} + +// Fix kotlinx-benchmarks bug +afterEvaluate { + val jvmBenchmarkJar by tasks.getting(org.gradle.jvm.tasks.Jar::class) { + duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.EXCLUDE + } +} + + +kotlin.sourceSets.all { + with(languageSettings) { + useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") + useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes") + useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") + } +} + +tasks.withType { + kotlinOptions { + jvmTarget = "11" + freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + } +} + + +readme { + maturity = Maturity.EXPERIMENTAL +} diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt similarity index 100% rename from examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt rename to benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt similarity index 100% rename from examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt rename to benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt similarity index 100% rename from examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt rename to benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt similarity index 100% rename from examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt rename to benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt similarity index 100% rename from examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt rename to benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt similarity index 100% rename from examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt rename to benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt similarity index 100% rename from examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt rename to benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt similarity index 100% rename from examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt rename to benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt similarity index 100% rename from examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt rename to benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt diff --git a/build.gradle.kts b/build.gradle.kts index 9b2200cb4..aeb4a6061 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,7 +25,7 @@ allprojects { } group = "space.kscience" - version = "0.3.0-dev-6" + version = "0.3.0-dev-7" } subprojects { diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 98d7b7073..8bd9423fe 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -8,29 +8,20 @@ import ru.mipt.npm.gradle.Maturity plugins { kotlin("jvm") - kotlin("plugin.allopen") - id("org.jetbrains.kotlinx.benchmark") } -allOpen.annotation("org.openjdk.jmh.annotations.State") -sourceSets.register("benchmarks") - repositories { + mavenCentral() jcenter() maven("https://repo.kotlin.link") maven("https://clojars.org/repo") maven("https://dl.bintray.com/egor-bogomolov/astminer/") maven("https://dl.bintray.com/hotkeytlt/maven") - maven("https://dl.bintray.com/kotlin/kotlin-eap") - maven("https://dl.bintray.com/kotlin/kotlinx") - maven("https://dl.bintray.com/mipt-npm/dev") - maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://jitpack.io") maven{ setUrl("http://logicrunch.research.it.uu.se/maven/") isAllowInsecureProtocol = true } - mavenCentral() } dependencies { @@ -48,7 +39,6 @@ dependencies { implementation(project(":kmath-for-real")) - implementation("org.deeplearning4j:deeplearning4j-core:1.0.0-beta7") implementation("org.nd4j:nd4j-native:1.0.0-beta7") // uncomment if your system supports AVX2 @@ -61,62 +51,9 @@ dependencies { // } else implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") - implementation("org.jetbrains.kotlinx:kotlinx-io:0.2.0-npm-dev-11") - implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.0") implementation("org.slf4j:slf4j-simple:1.7.30") - // plotting - implementation("kscience.plotlykt:plotlykt-server:0.3.1-dev") - - "benchmarksImplementation"("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:0.2.0-dev-20") - "benchmarksImplementation"(sourceSets.main.get().output + sourceSets.main.get().runtimeClasspath) -} - -// Configure benchmark -benchmark { - // Setup configurations - targets.register("benchmarks") - // This one matches sourceSet name above - - configurations.register("buffer") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds - include("BufferBenchmark") - } - - configurations.register("dot") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds - include("DotBenchmark") - } - - configurations.register("expressions") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds - include("ExpressionsInterpretersBenchmark") - } - - configurations.register("matrixInverse") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds - include("MatrixInverseBenchmark") - } - - configurations.register("bigInt") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds - include("BigIntBenchmark") - } + implementation("space.kscience:plotlykt-server:0.4.0-dev-2") } kotlin.sourceSets.all { diff --git a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt index be4dc461b..028985260 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -7,9 +7,6 @@ package space.kscience.kmath.commons.fit import kotlinx.html.br import kotlinx.html.h3 -import kscience.plotly.* -import kscience.plotly.models.ScatterMode -import kscience.plotly.models.TraceValues import space.kscience.kmath.commons.optimization.chiSquared import space.kscience.kmath.commons.optimization.minimize import space.kscience.kmath.distributions.NormalDistribution @@ -22,6 +19,9 @@ import space.kscience.kmath.real.step import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.asIterable import space.kscience.kmath.structures.toList +import space.kscience.plotly.* +import space.kscience.plotly.models.ScatterMode +import space.kscience.plotly.models.TraceValues import kotlin.math.pow import kotlin.math.sqrt diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index 43911e70d..1c2e8a0a2 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -12,10 +12,6 @@ plugins { } kotlin.sourceSets { - all { - languageSettings.useExperimentalAnnotation("kscience.kmath.misc.UnstableKMathAPI") - } - commonMain { dependencies { api(project(":kmath-core")) diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index a9a9177c0..885f3c227 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index 6ae0dcec6..d3a49aeb0 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -1,10 +1,3 @@ -/* - * 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. - */ - -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") @@ -16,7 +9,7 @@ dependencies { } readme { - maturity = Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index fc454205b..f6d12decd 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -1,10 +1,3 @@ -/* - * 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. - */ - -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -22,7 +15,7 @@ readme { All operations are specialized to work with `Double` numbers without declaring algebraic contexts. One can still use generic algebras though. """.trimIndent() - maturity = Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/settings.gradle.kts b/settings.gradle.kts index babad3672..553367a22 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -44,5 +44,6 @@ include( ":kmath-ast", ":kmath-ejml", ":kmath-kotlingrad", - ":examples" + ":examples", + ":benchmarks" ) From 41d0be8085849304758d832ff419aa8f431aa93e Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Fri, 16 Apr 2021 23:29:31 +0300 Subject: [PATCH 220/393] Increasing number of tests --- .../kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index 31fafaf75..e988103dd 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -18,10 +18,10 @@ internal class BigIntBenchmark { val kmNumber = BigIntField.number(Int.MAX_VALUE) val largeKmNumber = BigIntField { fun BigInt.pow10(): BigInt = power(10, ::multiply) - number(11).pow10().pow10().pow10() + number(11).pow10().pow10().pow10().pow10().pow10() } val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE) - val largeJvmNumber = JBigIntegerField { number(11).pow(1000) } + val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) } val bigExponent = 50_000 @Benchmark From 562e641b06b72639b12a6a88e4be4b698e305c13 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 17 Apr 2021 09:43:40 +0300 Subject: [PATCH 221/393] Fix benchmarks --- .../kmath/benchmarks/BigIntBenchmark.kt | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index e988103dd..4b19f8a63 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -5,23 +5,26 @@ package space.kscience.kmath.benchmarks -import edu.mcgill.kaliningraph.power + import kotlinx.benchmark.Blackhole import org.openjdk.jmh.annotations.Benchmark import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State -import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.BigInt +import space.kscience.kmath.operations.BigIntField +import space.kscience.kmath.operations.JBigIntegerField +import space.kscience.kmath.operations.invoke + +private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ONE) + @State(Scope.Benchmark) internal class BigIntBenchmark { val kmNumber = BigIntField.number(Int.MAX_VALUE) - val largeKmNumber = BigIntField { - fun BigInt.pow10(): BigInt = power(10, ::multiply) - number(11).pow10().pow10().pow10().pow10().pow10() - } val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE) - val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) } + val largeKmNumber = BigIntField { number(11).pow(100_000) } + val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) } val bigExponent = 50_000 @Benchmark @@ -41,7 +44,7 @@ internal class BigIntBenchmark { @Benchmark fun kmMultiplyLarge(blackhole: Blackhole) = BigIntField { - blackhole.consume(largeKmNumber.let { it * it }) + blackhole.consume(largeKmNumber*largeKmNumber) } @Benchmark @@ -51,12 +54,12 @@ internal class BigIntBenchmark { @Benchmark fun jvmMultiplyLarge(blackhole: Blackhole) = JBigIntegerField { - blackhole.consume(largeJvmNumber.let { it * it }) + blackhole.consume(largeJvmNumber*largeJvmNumber) } @Benchmark fun kmPower(blackhole: Blackhole) = BigIntField { - blackhole.consume(kmNumber.power(bigExponent, ::multiply)) + blackhole.consume(kmNumber.pow(bigExponent)) } @Benchmark From 3dc7038b6edac589da72ece0c135b93f62f2cb54 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 17 Apr 2021 09:46:10 +0300 Subject: [PATCH 222/393] Update BigIntBenchmark.kt unify definition (pow function seems to work wrong --- .../kmath/benchmarks/BigIntBenchmark.kt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index e988103dd..21222ddd3 100644 --- a/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/examples/src/benchmarks/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -12,16 +12,17 @@ import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State import space.kscience.kmath.operations.* + +private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ONE) + + @State(Scope.Benchmark) internal class BigIntBenchmark { val kmNumber = BigIntField.number(Int.MAX_VALUE) - val largeKmNumber = BigIntField { - fun BigInt.pow10(): BigInt = power(10, ::multiply) - number(11).pow10().pow10().pow10().pow10().pow10() - } val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE) - val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) } + val largeKmNumber = BigIntField { number(11).pow(100_000) } + val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) } val bigExponent = 50_000 @Benchmark @@ -41,7 +42,7 @@ internal class BigIntBenchmark { @Benchmark fun kmMultiplyLarge(blackhole: Blackhole) = BigIntField { - blackhole.consume(largeKmNumber.let { it * it }) + blackhole.consume(largeKmNumber*largeKmNumber) } @Benchmark @@ -51,16 +52,16 @@ internal class BigIntBenchmark { @Benchmark fun jvmMultiplyLarge(blackhole: Blackhole) = JBigIntegerField { - blackhole.consume(largeJvmNumber.let { it * it }) + blackhole.consume(largeJvmNumber*largeJvmNumber) } @Benchmark fun kmPower(blackhole: Blackhole) = BigIntField { - blackhole.consume(kmNumber.power(bigExponent, ::multiply)) + blackhole.consume(kmNumber.pow(bigExponent)) } @Benchmark fun jvmPower(blackhole: Blackhole) = JBigIntegerField { blackhole.consume(jvmNumber.pow(bigExponent)) } -} \ No newline at end of file +} From f67cfcc9e605106e6744d7c50cdee6d02c58065e Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 17 Apr 2021 09:47:34 +0300 Subject: [PATCH 223/393] Fix benchmarks --- .../kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index 66c034d06..b9a10c774 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -18,10 +18,6 @@ import space.kscience.kmath.operations.invoke private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ONE) - -private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ONE) - - @State(Scope.Benchmark) internal class BigIntBenchmark { From 6c215abf13c4cdc7839966634b0523d32de60f3f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 17 Apr 2021 10:08:04 +0300 Subject: [PATCH 224/393] Fix BigInt benchmark. --- .../kmath/benchmarks/BigIntBenchmark.kt | 21 +++++++++---------- .../kmath/integration/GaussIntegralTest.kt | 4 ++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index b9a10c774..2076aedc7 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -15,8 +15,7 @@ import space.kscience.kmath.operations.BigIntField import space.kscience.kmath.operations.JBigIntegerField import space.kscience.kmath.operations.invoke -private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ONE) - +private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ZERO) @State(Scope.Benchmark) internal class BigIntBenchmark { @@ -57,13 +56,13 @@ internal class BigIntBenchmark { blackhole.consume(largeJvmNumber*largeJvmNumber) } - @Benchmark - fun kmPower(blackhole: Blackhole) = BigIntField { - blackhole.consume(kmNumber.pow(bigExponent)) - } - - @Benchmark - fun jvmPower(blackhole: Blackhole) = JBigIntegerField { - blackhole.consume(jvmNumber.pow(bigExponent)) - } +// @Benchmark +// fun kmPower(blackhole: Blackhole) = BigIntField { +// blackhole.consume(kmNumber.pow(bigExponent)) +// } +// +// @Benchmark +// fun jvmPower(blackhole: Blackhole) = JBigIntegerField { +// blackhole.consume(jvmNumber.pow(bigExponent)) +// } } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 5ec90f42a..509821e61 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -19,7 +19,7 @@ class GaussIntegralTest { val res = DoubleField.integrate(0.0..2 * PI) { x -> sin(x) } - assertEquals(0.0, res.value!!, 1e-4) + assertEquals(0.0, res.value!!, 1e-2) } @Test @@ -31,7 +31,7 @@ class GaussIntegralTest { 0.0 } } - assertEquals(20.0, res.value!!, 0.5) + assertEquals(20.0, res.value!!, 1.0) } From 07e39a068d5055f34e2c3190beb242e4960b48f8 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 18 Apr 2021 19:43:03 +0300 Subject: [PATCH 225/393] Use split interval for integration. --- .../space/kscience/kmath/linear/gradient.kt | 4 +- .../kmath/commons/integration/CMIntegrator.kt | 2 +- .../integration/GaussRuleIntegrator.kt | 2 +- .../kmath/integration/GaussIntegrator.kt | 64 +++++++++++++++---- .../kmath/integration/UnivariateIntegrand.kt | 2 +- 5 files changed, 56 insertions(+), 18 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt index f7b284e89..a01ea7fe2 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt @@ -22,8 +22,8 @@ fun main() { return DoubleBuffer(x.size) { i -> val h = sigma[i] / 5 val dVector = DoubleBuffer(x.size) { if (it == i) h else 0.0 } - val f1 = invoke(x + dVector / 2) - val f0 = invoke(x - dVector / 2) + val f1 = this(x + dVector / 2) + val f0 = this(x - dVector / 2) (f1 - f0) / h } } diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt index 535c6b39e..92bf86128 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt @@ -28,7 +28,7 @@ public class CMIntegrator( val integrator = integratorBuilder(integrand) val maxCalls = integrand.getFeature()?.maxCalls ?: defaultMaxCalls val remainingCalls = maxCalls - integrand.calls - val range = integrand.getFeature>()?.range + val range = integrand.getFeature()?.range ?: error("Integration range is not provided") val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt index 071bac315..1c9915563 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt @@ -17,7 +17,7 @@ public class GaussRuleIntegrator( ) : UnivariateIntegrator { override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand { - val range = integrand.getFeature>()?.range + val range = integrand.getFeature()?.range ?: error("Integration range is not provided") val integrator: GaussIntegrator = getIntegrator(range) //TODO check performance diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index bc23e2f1b..749f3cc72 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -8,6 +8,13 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Field import space.kscience.kmath.structures.* +/** + * Set of univariate integration ranges. First components correspond to ranges themselves, second components to number of + * integration nodes per range + */ +public class UnivariateIntegrandRanges(public val ranges: List, Int>>) : IntegrandFeature { + public constructor(vararg pairs: Pair, Int>) : this(pairs.toList()) +} /** * A simple one-pass integrator based on Gauss rule @@ -18,9 +25,29 @@ public class GaussIntegrator( private fun buildRule(integrand: UnivariateIntegrand): Pair, Buffer> { val factory = integrand.getFeature() ?: GaussLegendreRuleFactory - val numPoints = integrand.getFeature()?.maxCalls ?: 100 - val range = integrand.getFeature>()?.range ?: 0.0..1.0 - return factory.build(numPoints, range) + val predefinedRanges = integrand.getFeature() + if (predefinedRanges == null || predefinedRanges.ranges.isEmpty()) { + val numPoints = integrand.getFeature()?.maxCalls ?: 100 + val range = integrand.getFeature()?.range ?: 0.0..1.0 + return factory.build(numPoints, range) + } else { + val ranges = predefinedRanges.ranges + var counter = 0 + val length = ranges.sumOf { it.second } + val pointsArray = DoubleArray(length) + val weightsArray = DoubleArray(length) + + for (range in ranges) { + val rule = factory.build(range.second, range.first) + repeat(rule.first.size) { i -> + pointsArray[counter] = rule.first[i] + weightsArray[counter] = rule.second[i] + counter++ + } + + } + return pointsArray.asBuffer() to weightsArray.asBuffer() + } } override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand = with(algebra) { @@ -49,7 +76,8 @@ public class GaussIntegrator( * Following features are evaluated: * * [GaussIntegratorRuleFactory] - A factory for computing the Gauss integration rule. By default uses [GaussLegendreRuleFactory] * * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. - * * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 100 points. + * * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 10 points. + * * [UnivariateIntegrandRanges] - Set of ranges and number of points per range. Defaults to given [IntegrationRange] and [IntegrandMaxCalls] */ @UnstableKMathAPI public fun Field.integrate( @@ -64,15 +92,25 @@ public fun Field.integrate( @UnstableKMathAPI public fun Field.integrate( range: ClosedRange, - numPoints: Int = 100, + order: Int = 10, + intervals: Int = 10, vararg features: IntegrandFeature, function: (Double) -> T, -): UnivariateIntegrand = GaussIntegrator(this).integrate( - UnivariateIntegrand( - function, - IntegrationRange(range), - GaussLegendreRuleFactory, - IntegrandMaxCalls(numPoints), - *features +): UnivariateIntegrand { + require(range.endInclusive > range.start) { "The range upper bound should be higher than lower bound" } + require(order > 1) { "The order of polynomial must be more than 1" } + require(intervals > 0) { "Number of intervals must be positive" } + val rangeSize = (range.endInclusive - range.start) / intervals + val ranges = UnivariateIntegrandRanges( + (0 until intervals).map { i -> (rangeSize * i)..(rangeSize * i + 1) to order } ) -) \ No newline at end of file + return GaussIntegrator(this).integrate( + UnivariateIntegrand( + function, + IntegrationRange(range), + GaussLegendreRuleFactory, + ranges, + *features + ) + ) +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index 0b41a3f8b..bcd5005c4 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -33,7 +33,7 @@ public fun UnivariateIntegrand( public typealias UnivariateIntegrator = Integrator> @JvmInline -public value class IntegrationRange>(public val range: ClosedRange) : IntegrandFeature +public value class IntegrationRange(public val range: ClosedRange) : IntegrandFeature public val UnivariateIntegrand.value: T? get() = getFeature>()?.value From 86818f6864ac722ebd5b32f2274c9eb6afb06ca0 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 19 Apr 2021 09:31:56 +0300 Subject: [PATCH 226/393] Replace dl4j with nd4j dependency --- kmath-nd4j/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 17232b44f..c7d891206 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -13,7 +13,7 @@ plugins { dependencies { api(project(":kmath-core")) api("org.nd4j:nd4j-api:1.0.0-beta7") - testImplementation("org.deeplearning4j:deeplearning4j-core:1.0.0-beta7") + testImplementation("org.nd4j:nd4j-native:1.0.0-beta7") testImplementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") testImplementation("org.slf4j:slf4j-simple:1.7.30") } From fd4108b74fbd012796fa12f913675ed55d8eae62 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 19 Apr 2021 11:26:06 +0300 Subject: [PATCH 227/393] fix segmented integral --- .../space/kscience/kmath/integration/GaussIntegrator.kt | 2 +- .../space/kscience/kmath/integration/GaussIntegralTest.kt | 4 ++-- .../kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index 749f3cc72..ae82a40be 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -102,7 +102,7 @@ public fun Field.integrate( require(intervals > 0) { "Number of intervals must be positive" } val rangeSize = (range.endInclusive - range.start) / intervals val ranges = UnivariateIntegrandRanges( - (0 until intervals).map { i -> (rangeSize * i)..(rangeSize * i + 1) to order } + (0 until intervals).map { i -> (rangeSize * i)..(rangeSize * (i + 1)) to order } ) return GaussIntegrator(this).integrate( UnivariateIntegrand( diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 509821e61..195711452 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -24,14 +24,14 @@ class GaussIntegralTest { @Test fun gaussUniform() { - val res = DoubleField.integrate(0.0..100.0,300) { x -> + val res = DoubleField.integrate(0.0..100.0) { x -> if(x in 30.0..50.0){ 1.0 } else { 0.0 } } - assertEquals(20.0, res.value!!, 1.0) + assertEquals(20.0, res.value!!, 0.5) } diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt index b9aa251d2..79db86fcc 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt @@ -20,8 +20,7 @@ public sealed class Nd4jArrayStructure : MutableStructureND { */ public abstract val ndArray: INDArray - public override val shape: IntArray - get() = ndArray.shape().toIntArray() + public override val shape: IntArray get() = ndArray.shape().toIntArray() internal abstract fun elementsIterator(): Iterator> internal fun indicesIterator(): Iterator = ndArray.indicesIterator() From 84fa878ee328f1c6f2ad828a77b83b325df222eb Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 20 Apr 2021 19:14:59 +0700 Subject: [PATCH 228/393] Update dependencies --- kmath-ast/build.gradle.kts | 30 ++++++------------- .../kotlin/space/kscience/kmath/ast/parser.kt | 2 -- 2 files changed, 9 insertions(+), 23 deletions(-) rename kmath-ast/src/{jvmMain => commonMain}/kotlin/space/kscience/kmath/ast/parser.kt (98%) diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 3f309b67c..f2080d0b2 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -27,6 +27,7 @@ kotlin.js { kotlin.sourceSets { commonMain { dependencies { + api("com.github.h0tk3y.betterParse:better-parse:0.4.2") api(project(":kmath-core")) } } @@ -39,13 +40,12 @@ kotlin.sourceSets { jsMain { dependencies { - implementation(npm("astring", "1.7.0")) + implementation(npm("astring", "1.7.4")) } } jvmMain { dependencies { - api("com.github.h0tk3y.betterParse:better-parse:0.4.1") implementation("org.ow2.asm:asm:9.1") implementation("org.ow2.asm:asm-commons:9.1") } @@ -64,25 +64,7 @@ readme { feature( id = "expression-language", description = "Expression language and its parser", - ref = "src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt" - ) - - feature( - id = "mst", - description = "MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation", - ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt" - ) - - feature( - id = "mst-building", - description = "MST building algebraic structure", - ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt" - ) - - feature( - id = "mst-interpreter", - description = "MST interpreter", - ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt" + ref = "src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt" ) feature( @@ -96,4 +78,10 @@ readme { description = "Dynamic MST to JS compiler", ref = "src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt" ) + + feature( + id = "rendering", + description = "Extendable MST rendering", + ref = "src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt" + ) } diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt similarity index 98% rename from kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt rename to kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt index 025f4984c..d2e92c37f 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -// TODO move to common when https://github.com/h0tk3y/better-parse/pull/37 is merged - package space.kscience.kmath.ast import com.github.h0tk3y.betterParse.combinators.* From 9c353f4a0d3e0d2c09d8551b9efdc492fc43dbab Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 20 Apr 2021 22:48:09 +0300 Subject: [PATCH 229/393] Make ND4J float algebra extended --- CHANGELOG.md | 1 + .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 46 +++++++++++++++++-- .../kmath/nd4j/Nd4jArrayAlgebraTest.kt | 14 ++++++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1d33a75a..7464695ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Blocking chains and Statistics - Multiplatform integration - Integration for any Field element +- Extendend operations for ND4J fields ### Changed - Exponential operations merged with hyperbolic functions diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index f2c69adee..0205f1c87 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -6,7 +6,10 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray +import org.nd4j.linalg.api.ops.impl.scalar.Pow +import org.nd4j.linalg.api.ops.impl.transforms.strict.* import org.nd4j.linalg.factory.Nd4j +import org.nd4j.linalg.ops.transforms.Transforms import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* @@ -207,7 +210,8 @@ public interface Nd4jArrayField> : FieldND, Nd4jArrayRing< /** * Represents [FieldND] over [Nd4jArrayDoubleStructure]. */ -public class DoubleNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField { +public class DoubleNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField, + ExtendedField> { public override val elementContext: DoubleField get() = DoubleField public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asDoubleStructure() @@ -239,14 +243,31 @@ public class DoubleNd4jArrayField(public override val shape: IntArray) : Nd4jArr public override operator fun Double.minus(arg: StructureND): Nd4jArrayStructure { return arg.ndArray.rsub(this).wrap() } + + override fun sin(arg: StructureND): StructureND = Transforms.sin(arg.ndArray).wrap() + + override fun cos(arg: StructureND): StructureND = Transforms.cos(arg.ndArray).wrap() + + override fun asin(arg: StructureND): StructureND = Transforms.asin(arg.ndArray).wrap() + + override fun acos(arg: StructureND): StructureND = Transforms.acos(arg.ndArray).wrap() + + override fun atan(arg: StructureND): StructureND = Transforms.atan(arg.ndArray).wrap() + + override fun power(arg: StructureND, pow: Number): StructureND = + Transforms.pow(arg.ndArray,pow).wrap() + + override fun exp(arg: StructureND): StructureND = Transforms.exp(arg.ndArray).wrap() + + override fun ln(arg: StructureND): StructureND = Transforms.log(arg.ndArray).wrap() } /** * Represents [FieldND] over [Nd4jArrayStructure] of [Float]. */ -public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField { - public override val elementContext: FloatField - get() = FloatField +public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField, + ExtendedField> { + public override val elementContext: FloatField get() = FloatField public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asFloatStructure() @@ -270,6 +291,23 @@ public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArra public override operator fun Float.minus(arg: StructureND): Nd4jArrayStructure = arg.ndArray.rsub(this).wrap() + + override fun sin(arg: StructureND): StructureND = Sin(arg.ndArray).z().wrap() + + override fun cos(arg: StructureND): StructureND = Cos(arg.ndArray).z().wrap() + + override fun asin(arg: StructureND): StructureND = ASin(arg.ndArray).z().wrap() + + override fun acos(arg: StructureND): StructureND = ACos(arg.ndArray).z().wrap() + + override fun atan(arg: StructureND): StructureND = ATan(arg.ndArray).z().wrap() + + override fun power(arg: StructureND, pow: Number): StructureND = + Pow(arg.ndArray, pow.toDouble()).z().wrap() + + override fun exp(arg: StructureND): StructureND = Exp(arg.ndArray).z().wrap() + + override fun ln(arg: StructureND): StructureND = Log(arg.ndArray).z().wrap() } /** diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt index c3874b249..b6c524cc6 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt @@ -6,8 +6,12 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.factory.Nd4j +import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.operations.invoke +import kotlin.math.PI import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertTrue import kotlin.test.fail internal class Nd4jArrayAlgebraTest { @@ -43,4 +47,14 @@ internal class Nd4jArrayAlgebraTest { expected[intArrayOf(1, 1)] = 26 assertEquals(expected, res) } + + @Test + fun testSin() = DoubleNd4jArrayField(intArrayOf(2, 2)).invoke { + val initial = produce { (i, j) -> if (i == j) PI/2 else 0.0 } + val transformed = sin(initial) + val expected = produce { (i, j) -> if (i == j) 1.0 else 0.0 } + + println(transformed) + assertTrue { StructureND.contentEquals(transformed, expected) } + } } From 6aa5b547b57092f12a6a2defbfd94b65c5d4f3e9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 21 Apr 2021 12:48:11 +0300 Subject: [PATCH 230/393] cleanup --- CHANGELOG.md | 1 + kmath-core/api/kmath-core.api | 12 ++--- .../kmath/expressions/SymbolIndexer.kt | 4 +- .../kmath/expressions/expressionBuilders.kt | 45 ------------------- .../space/kscience/kmath/misc/Symbol.kt | 25 ++++++++++- .../kscience/kmath/operations/Algebra.kt | 4 +- .../kmath/operations/NumericAlgebra.kt | 6 +-- .../kscience/kmath/operations/numbers.kt | 6 --- 8 files changed, 35 insertions(+), 68 deletions(-) delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 7464695ec..c41eda374 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ - Number multiplication and division in main Algebra chain - `contentEquals` from Buffer. It moved to the companion. - MSTExpression +- Expression algebra builders ### Fixed - Ring inherits RingOperations, not GroupOperations diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 6b300123c..efb626c12 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -45,13 +45,6 @@ public abstract interface class space/kscience/kmath/expressions/ExpressionAlgeb public abstract fun const (Ljava/lang/Object;)Ljava/lang/Object; } -public final class space/kscience/kmath/expressions/ExpressionBuildersKt { - public static final fun extendedFieldExpression (Lspace/kscience/kmath/operations/ExtendedField;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; - public static final fun fieldExpression (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; - public static final fun ringExpression (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; - public static final fun spaceExpression (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/Expression; -} - public final class space/kscience/kmath/expressions/ExpressionKt { public static final fun binding (Lspace/kscience/kmath/expressions/ExpressionAlgebra;)Lkotlin/properties/ReadOnlyProperty; public static final fun callByString (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object; @@ -705,7 +698,11 @@ public final class space/kscience/kmath/misc/Symbol$Companion { } public final class space/kscience/kmath/misc/SymbolKt { + public static final fun get (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object; + public static final fun get (Ljava/util/Map;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; public static final fun getSymbol ()Lkotlin/properties/ReadOnlyProperty; + public static final fun set (Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)V + public static final fun set (Ljava/util/Map;Lspace/kscience/kmath/misc/Symbol;Ljava/lang/Object;)V } public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation { @@ -1209,7 +1206,6 @@ public abstract interface class space/kscience/kmath/operations/ExtendedField : public fun acosh (Ljava/lang/Object;)Ljava/lang/Object; public fun asinh (Ljava/lang/Object;)Ljava/lang/Object; public fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun rightSideNumberOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun sinh (Ljava/lang/Object;)Ljava/lang/Object; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt index 886008983..738156975 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt @@ -33,12 +33,12 @@ public interface SymbolIndexer { public operator fun DoubleArray.get(symbol: Symbol): Double { require(size == symbols.size) { "The input array size for indexer should be ${symbols.size} but $size found" } - return get(this@SymbolIndexer.indexOf(symbol)) + return get(indexOf(symbol)) } public operator fun Point.get(symbol: Symbol): T { require(size == symbols.size) { "The input buffer size for indexer should be ${symbols.size} but $size found" } - return get(this@SymbolIndexer.indexOf(symbol)) + return get(indexOf(symbol)) } public fun DoubleArray.toMap(): Map { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt deleted file mode 100644 index 142194070..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/expressionBuilders.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.expressions - -import space.kscience.kmath.operations.ExtendedField -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.Ring -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - - -/** - * Creates a functional expression with this [Ring]. - */ -public inline fun Ring.spaceExpression(block: FunctionalExpressionGroup>.() -> Expression): Expression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return FunctionalExpressionGroup(this).block() -} - -/** - * Creates a functional expression with this [Ring]. - */ -public inline fun Ring.ringExpression(block: FunctionalExpressionRing>.() -> Expression): Expression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return FunctionalExpressionRing(this).block() -} - -/** - * Creates a functional expression with this [Field]. - */ -public inline fun Field.fieldExpression(block: FunctionalExpressionField>.() -> Expression): Expression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return FunctionalExpressionField(this).block() -} - -/** - * Creates a functional expression with this [ExtendedField]. - */ -public inline fun ExtendedField.extendedFieldExpression(block: FunctionalExpressionExtendedField>.() -> Expression): Expression { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return FunctionalExpressionExtendedField(this).block() -} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt index 737acc025..b9fb6879a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt @@ -32,10 +32,33 @@ public value class StringSymbol(override val identity: String) : Symbol { override fun toString(): String = identity } - /** * A delegate to create a symbol with a string identity in this scope */ public val symbol: ReadOnlyProperty = ReadOnlyProperty { _, property -> StringSymbol(property.name) } + +/** + * Ger a value from a [String]-keyed map by a [Symbol] + */ +public operator fun Map.get(symbol: Symbol): T? = get(symbol.identity) + +/** + * Set a value of [String]-keyed map by a [Symbol] + */ +public operator fun MutableMap.set(symbol: Symbol, value: T){ + set(symbol.identity, value) +} + +/** + * Get a value from a [Symbol]-keyed map by a [String] + */ +public operator fun Map.get(string: String): T? = get(StringSymbol(string)) + +/** + * Set a value of [String]-keyed map by a [Symbol] + */ +public operator fun MutableMap.set(string: String, value: T){ + set(StringSymbol(string), value) +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 0334e0466..c994580bd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -44,9 +44,9 @@ public interface Algebra { /** * Dynamically dispatches an unary operation with the certain name. * - * This function must follow two properties: + * This function must has two features: * - * 1. In case if operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. + * 1. In case operation is not defined in the structure, the function throws [kotlin.IllegalStateException]. * 2. This function is symmetric with second `unaryOperation` overload: * i.e. `unaryOperationFunction(a)(b) == unaryOperation(a, b)`. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt index 6a35828ee..deeb07e0e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt @@ -97,14 +97,12 @@ public interface NumericAlgebra : Algebra { /** * The π mathematical constant. */ -public val NumericAlgebra.pi: T - get() = bindSymbolOrNull("pi") ?: number(PI) +public val NumericAlgebra.pi: T get() = bindSymbolOrNull("pi") ?: number(PI) /** * The *e* mathematical constant. */ -public val NumericAlgebra.e: T - get() = number(E) +public val NumericAlgebra.e: T get() = number(E) /** * Scale by scalar operations diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt index 3b0abf657..0d6d9e98d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt @@ -49,12 +49,6 @@ public interface ExtendedField : ExtendedFieldOperations, Field, Numeri public override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one))) public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2.0 - public override fun bindSymbol(value: String): T = when (value) { - "pi" -> pi - "e" -> e - else -> super.bindSymbol(value) - } - public override fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T = when (operation) { PowerOperations.POW_OPERATION -> ::power From b6a57dbfd03e4eae9232891bc6fa00e3647b77ce Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 20 Apr 2021 21:39:45 +0700 Subject: [PATCH 231/393] MST compilation to WebAssembly with Binaryen, reorganize internal JS bindings, tests refactor --- README.md | 16 +- benchmarks/build.gradle.kts | 40 +- .../ExpressionsInterpretersBenchmark.kt | 59 +- build.gradle.kts | 10 +- examples/build.gradle.kts | 7 +- .../kscience/kmath/ast/kotlingradSupport.kt | 2 +- kmath-ast/README.md | 54 +- kmath-ast/build.gradle.kts | 7 +- kmath-ast/docs/README-TEMPLATE.md | 40 +- .../space/kscisnce/kmath/ast/InterpretTest.kt | 27 - .../kmath/ast/ParserPrecedenceTest.kt | 15 +- .../space/kscisnce}/kmath/ast/ParserTest.kt | 25 +- .../space/kscience/kmath/estree/estree.kt | 2 +- .../kmath/estree/internal/ESTreeBuilder.kt | 9 +- .../kmath/estree/internal/stream/stream.kt | 12 - .../{estree => }/internal/astring/astring.kt | 4 +- .../internal/astring/astring.typealises.kt | 3 + .../kscience/kmath/internal/base64/base64.kt | 49 + .../kmath/internal/binaryen/index.binaryen.kt | 2234 +++++++++++++++++ .../binaryen/index.binaryen.typealiases.kt | 11 + .../{estree => }/internal/emitter/emitter.kt | 2 +- .../internal/estree/estree.extensions.kt | 2 +- .../{estree => }/internal/estree/estree.kt | 2 +- .../kscience/kmath/internal/stream/stream.kt | 7 + .../internal/tsstdlib/lib.es2015.iterable.kt | 2 +- .../{estree => }/internal/tsstdlib/lib.es5.kt | 11 +- .../lib.dom.WebAssembly.module_dukat.kt | 231 ++ .../nonDeclarations.WebAssembly.kt | 22 + .../kmath/wasm/internal/WasmBuilder.kt | 155 ++ .../wasm/internal/f64StandardFunctions.kt | 8 + .../kotlin/space/kscience/kmath/wasm/wasm.kt | 77 + .../kscience/kmath/ast/TestExecutionTime.kt | 67 + .../TestESTreeConsistencyWithInterpreter.kt | 35 +- .../estree/TestESTreeOperationsSupport.kt | 27 +- .../kmath/estree/TestESTreeSpecialization.kt | 43 +- .../kmath/estree/TestESTreeVariables.kt | 12 +- .../TestWasmConsistencyWithInterpreter.kt | 60 + .../kmath/wasm/TestWasmOperationsSupport.kt | 42 + .../kmath/wasm/TestWasmSpecialization.kt | 76 + .../kscience/kmath/wasm/TestWasmSpecific.kt | 48 + .../kscience/kmath/wasm/TestWasmVariables.kt | 34 + .../asm/TestAsmConsistencyWithInterpreter.kt | 19 +- .../kmath/asm/TestAsmOperationsSupport.kt | 25 +- .../kmath/asm/TestAsmSpecialization.kt | 43 +- .../kscience/kmath/asm/TestAsmVariables.kt | 12 +- .../kmath/ast/rendering/TestFeatures.kt | 100 - .../kscience/kmath/ast/rendering/TestLatex.kt | 73 - .../kmath/ast/rendering/TestMathML.kt | 92 - .../kmath/ast/rendering/TestStages.kt | 33 - .../kscience/kmath/ast/rendering/TestUtils.kt | 46 - kmath-complex/README.md | 6 +- kmath-complex/build.gradle.kts | 4 +- kmath-core/README.md | 6 +- kmath-core/build.gradle.kts | 4 +- .../kmath/expressions/InterpretTest.kt | 18 + kmath-coroutines/build.gradle.kts | 4 +- kmath-ejml/README.md | 6 +- kmath-for-real/README.md | 6 +- kmath-functions/README.md | 6 +- kmath-geometry/build.gradle.kts | 4 +- kmath-histograms/build.gradle.kts | 4 +- .../kmath/kotlingrad/AdaptingTests.kt | 25 +- kmath-nd4j/README.md | 6 +- kmath-nd4j/build.gradle.kts | 4 +- kmath-stat/build.gradle.kts | 4 +- kmath-viktor/build.gradle.kts | 4 +- 66 files changed, 3451 insertions(+), 692 deletions(-) delete mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt rename kmath-ast/src/{jvmTest/kotlin/space/kscience => commonTest/kotlin/space/kscisnce}/kmath/ast/ParserPrecedenceTest.kt (75%) rename kmath-ast/src/{jvmTest/kotlin/space/kscience => commonTest/kotlin/space/kscisnce}/kmath/ast/ParserTest.kt (67%) delete mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/stream/stream.kt rename kmath-ast/src/jsMain/kotlin/space/kscience/kmath/{estree => }/internal/astring/astring.kt (90%) create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt rename kmath-ast/src/jsMain/kotlin/space/kscience/kmath/{estree => }/internal/emitter/emitter.kt (91%) rename kmath-ast/src/jsMain/kotlin/space/kscience/kmath/{estree => }/internal/estree/estree.extensions.kt (97%) rename kmath-ast/src/jsMain/kotlin/space/kscience/kmath/{estree => }/internal/estree/estree.kt (99%) create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt rename kmath-ast/src/jsMain/kotlin/space/kscience/kmath/{estree => }/internal/tsstdlib/lib.es2015.iterable.kt (94%) rename kmath-ast/src/jsMain/kotlin/space/kscience/kmath/{estree => }/internal/tsstdlib/lib.es5.kt (88%) create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt diff --git a/README.md b/README.md index 0210b4caf..773eb6398 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,12 @@ KMath is a modular library. Different modules provide different features with di
+* ### [benchmarks](benchmarks) +> +> +> **Maturity**: EXPERIMENTAL +
+ * ### [examples](examples) > > @@ -88,12 +94,10 @@ KMath is a modular library. Different modules provide different features with di > **Maturity**: PROTOTYPE > > **Features:** -> - [expression-language](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser -> - [mst](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation -> - [mst-building](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure -> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter +> - [expression-language](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser > - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler > - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler +> - [rendering](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt) : Extendable MST rendering
@@ -266,8 +270,8 @@ repositories { } dependencies { - api("space.kscience:kmath-core:0.3.0-dev-6") - // api("space.kscience:kmath-core-jvm:0.3.0-dev-6") for jvm-specific version + api("space.kscience:kmath-core:0.3.0-dev-7") + // api("space.kscience:kmath-core-jvm:0.3.0-dev-7") for jvm-specific version } ``` diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index f8e85395b..d6796ed46 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") kotlin("plugin.allopen") @@ -14,8 +12,6 @@ plugins { allOpen.annotation("org.openjdk.jmh.annotations.State") sourceSets.register("benchmarks") - - repositories { mavenCentral() jcenter() @@ -77,43 +73,35 @@ benchmark { register("jvm") } + fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() { + warmups = 1 + iterations = 5 + iterationTime = 1000 + iterationTimeUnit = "ms" + } + configurations.register("buffer") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + commonConfiguration() include("BufferBenchmark") } configurations.register("dot") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + commonConfiguration() include("DotBenchmark") } configurations.register("expressions") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + commonConfiguration() include("ExpressionsInterpretersBenchmark") } configurations.register("matrixInverse") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + commonConfiguration() include("MatrixInverseBenchmark") } configurations.register("bigInt") { - warmups = 1 // number of warmup iterations - iterations = 3 // number of iterations - iterationTime = 500 // time in seconds per iteration - iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds + commonConfiguration() include("BigIntBenchmark") } } @@ -121,7 +109,7 @@ benchmark { // Fix kotlinx-benchmarks bug afterEvaluate { val jvmBenchmarkJar by tasks.getting(org.gradle.jvm.tasks.Jar::class) { - duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.EXCLUDE + duplicatesStrategy = DuplicatesStrategy.EXCLUDE } } @@ -143,5 +131,5 @@ tasks.withType { readme { - maturity = Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index d6fde8398..942fba308 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -11,6 +11,7 @@ import kotlinx.benchmark.Scope import kotlinx.benchmark.State import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.expressions.* +import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol @@ -20,50 +21,22 @@ import kotlin.random.Random @State(Scope.Benchmark) internal class ExpressionsInterpretersBenchmark { @Benchmark - fun functionalExpression(blackhole: Blackhole) { - val expr = algebra.expressionInField { - val x = bindSymbol(x) - x * const(2.0) + const(2.0) / x - const(16.0) - } - - invokeAndSum(expr, blackhole) - } + fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole) @Benchmark - fun mstExpression(blackhole: Blackhole) { - val expr = MstField { - val x = bindSymbol(x) - x * 2.0 + number(2.0) / x - 16.0 - }.toExpression(algebra) - - invokeAndSum(expr, blackhole) - } + fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole) @Benchmark - fun asmExpression(blackhole: Blackhole) { - val expr = MstField { - val x = bindSymbol(x) - x * 2.0 + number(2.0) / x - 16.0 - }.compileToExpression(algebra) - - invokeAndSum(expr, blackhole) - } + fun asmExpression(blackhole: Blackhole) = invokeAndSum(asm, blackhole) @Benchmark - fun rawExpression(blackhole: Blackhole) { - val expr = Expression { args -> - val x = args.getValue(x) - x * 2.0 + 2.0 / x - 16.0 - } - - invokeAndSum(expr, blackhole) - } + fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole) private fun invokeAndSum(expr: Expression, blackhole: Blackhole) { val random = Random(0) var sum = 0.0 - repeat(1000000) { + repeat(times) { sum += expr(x to random.nextDouble()) } @@ -71,7 +44,23 @@ internal class ExpressionsInterpretersBenchmark { } private companion object { - private val algebra = DoubleField - private val x by symbol + private val x: Symbol by symbol + private val algebra: DoubleField = DoubleField + private const val times = 1_000_000 + + private val functional: Expression = DoubleField.expressionInExtendedField { + bindSymbol(x) * number(2.0) + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x)) + } + + private val node = MstExtendedField { + bindSymbol(x) * 2.0 + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x)) + } + + private val mst: Expression = node.toExpression(DoubleField) + private val asm: Expression = node.compileToExpression(DoubleField) + + private val raw: Expression = Expression { args -> + args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 / kotlin.math.sin(args.getValue(x)) + } } } diff --git a/build.gradle.kts b/build.gradle.kts index aeb4a6061..a7c9144a7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,9 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import org.jetbrains.dokka.gradle.DokkaTask -import java.net.URL - plugins { id("ru.mipt.npm.gradle.project") } @@ -17,8 +14,7 @@ allprojects { maven("https://dl.bintray.com/egor-bogomolov/astminer/") maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://jitpack.io") - maven{ - setUrl("http://logicrunch.research.it.uu.se/maven/") + maven("http://logicrunch.research.it.uu.se/maven/") { isAllowInsecureProtocol = true } mavenCentral() @@ -32,7 +28,7 @@ subprojects { if (name.startsWith("kmath")) apply() afterEvaluate { - tasks.withType { + tasks.withType { dokkaSourceSets.all { val readmeFile = File(this@subprojects.projectDir, "./README.md") if (readmeFile.exists()) @@ -42,7 +38,7 @@ subprojects { "http://ejml.org/javadoc/", "https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/", "https://deeplearning4j.org/api/latest/" - ).map { URL("${it}package-list") to URL(it) }.forEach { (a, b) -> + ).map { java.net.URL("${it}package-list") to java.net.URL(it) }.forEach { (a, b) -> externalDocumentationLink { packageListUrl.set(a) url.set(b) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 8bd9423fe..67fe9853a 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -3,9 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("jvm") } @@ -64,7 +61,7 @@ kotlin.sourceSets.all { } } -tasks.withType { +tasks.withType { kotlinOptions{ jvmTarget = "11" freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" @@ -72,5 +69,5 @@ tasks.withType { } readme { - maturity = Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt index 4a31f33a3..25f42f5a9 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt @@ -25,5 +25,5 @@ fun main() { val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField) - assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0)) + assert(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0)) } diff --git a/kmath-ast/README.md b/kmath-ast/README.md index b1ef9c7d3..eedba16fa 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -2,17 +2,15 @@ Abstract syntax tree expression representation and related optimizations. - - [expression-language](src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser - - [mst](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation - - [mst-building](src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure - - [mst-interpreter](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter + - [expression-language](src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser - [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler - [mst-js-codegen](src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler + - [rendering](src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt) : Extendable MST rendering ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-7`. **Gradle:** ```gradle @@ -23,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0-dev-6' + implementation 'space.kscience:kmath-ast:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -35,7 +33,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0-dev-6") + implementation("space.kscience:kmath-ast:0.3.0-dev-7") } ``` @@ -49,10 +47,10 @@ a special implementation of `Expression` with implemented `invoke` function. For example, the following builder: ```kotlin -DoubleField.mstInField { symbol("x") + 2 }.compile() +MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -… leads to generation of bytecode, which can be decompiled to the following Java class: +… leads to generation of bytecode, which can be decompiled to the following Java class: ```java package space.kscience.kmath.asm.generated; @@ -77,15 +75,6 @@ public final class AsmCompiledExpression_45045_0 implements Expression { ``` -### Example Usage - -This API extends MST and MstExpression, so you may optimize as both of them: - -```kotlin -DoubleField.mstInField { symbol("x") + 2 }.compile() -DoubleField.expression("x+2".parseMath()) -``` - #### Known issues - The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid @@ -97,7 +86,7 @@ DoubleField.expression("x+2".parseMath()) A similar feature is also available on JS. ```kotlin -DoubleField.mstInField { symbol("x") + 2 }.compile() +MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` The code above returns expression implemented with such a JS function: @@ -108,13 +97,32 @@ var executable = function (constants, arguments) { }; ``` + +```kotlin +import space.kscience.kmath.wasm.* + +MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) +``` + +An example of emitted WASM IR in the form of WAT: + +```lisp +(func $executable (param $0 f64) (result f64) + (f64.add + (local.get $0) + (f64.const 2) + ) +) +``` + #### Known issues -- This feature uses `eval` which can be unavailable in several environments. +- ESTree expression compilation uses `eval` which can be unavailable in several environments. +- WebAssembly isn't supported by old versions of browsers (see https://webassembly.org/roadmap/). ## Rendering expressions -kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax. +kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax. Example usage: @@ -135,7 +143,7 @@ public fun main() { } ``` -Result LaTeX: +Result LaTeX: ![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D) @@ -145,5 +153,5 @@ Result MathML (embedding MathML is not allowed by GitHub Markdown): ex-sin-12x2×1010+x3-12 ``` -It is also possible to create custom algorithms of render, and even add support of other markup languages +It is also possible to create custom algorithms of render, and even add support of other markup languages (see API reference). diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index f2080d0b2..15357b2d5 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -41,6 +39,9 @@ kotlin.sourceSets { jsMain { dependencies { implementation(npm("astring", "1.7.4")) + implementation(npm("binaryen", "100.0")) + implementation(npm("js-base64", "3.6.0")) + implementation(npm("webassembly", "0.11.0")) } } @@ -58,7 +59,7 @@ tasks.dokkaHtml { } readme { - maturity = Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index 9ed44d584..b38311ea1 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -16,7 +16,7 @@ a special implementation of `Expression` with implemented `invoke` function. For example, the following builder: ```kotlin -DoubleField.mstInField { symbol("x") + 2 }.compile() +MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` … leads to generation of bytecode, which can be decompiled to the following Java class: @@ -44,15 +44,6 @@ public final class AsmCompiledExpression_45045_0 implements Expression { ``` -### Example Usage - -This API extends MST and MstExpression, so you may optimize as both of them: - -```kotlin -DoubleField.mstInField { symbol("x") + 2 }.compile() -DoubleField.expression("x+2".parseMath()) -``` - #### Known issues - The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid @@ -64,7 +55,7 @@ DoubleField.expression("x+2".parseMath()) A similar feature is also available on JS. ```kotlin -DoubleField.mstInField { symbol("x") + 2 }.compile() +MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` The code above returns expression implemented with such a JS function: @@ -75,13 +66,32 @@ var executable = function (constants, arguments) { }; ``` + +```kotlin +import space.kscience.kmath.wasm.* + +MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) +``` + +An example of emitted WASM IR in the form of WAT: + +```lisp +(func \$executable (param \$0 f64) (result f64) + (f64.add + (local.get \$0) + (f64.const 2) + ) +) +``` + #### Known issues -- This feature uses `eval` which can be unavailable in several environments. +- ESTree expression compilation uses `eval` which can be unavailable in several environments. +- WebAssembly isn't supported by old versions of browsers (see https://webassembly.org/roadmap/). ## Rendering expressions -kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax. +kmath-ast also includes an extensible engine to display expressions in LaTeX or MathML syntax. Example usage: @@ -102,7 +112,7 @@ public fun main() { } ``` -Result LaTeX: +Result LaTeX: ![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D) @@ -112,5 +122,5 @@ Result MathML (embedding MathML is not allowed by GitHub Markdown): ex-sin-12x2×1010+x3-12 ``` -It is also possible to create custom algorithms of render, and even add support of other markup languages +It is also possible to create custom algorithms of render, and even add support of other markup languages (see API reference). diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt deleted file mode 100644 index 93fde5aab..000000000 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/InterpretTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscisnce.kmath.ast - -import space.kscience.kmath.expressions.MstField -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.expressions.toExpression -import space.kscience.kmath.misc.Symbol.Companion.x -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test - -class InterpretTest { - - @Test - fun interpretation(){ - val expr = MstField { - val x = bindSymbol(x) - x * 2.0 + number(2.0) / x - 16.0 - }.toExpression(DoubleField) - expr(x to 2.2) - } -} \ No newline at end of file diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt similarity index 75% rename from kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt index 6273eff27..509f87d98 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt @@ -1,19 +1,12 @@ -/* - * 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.ast +package space.kscisnce.kmath.ast +import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.evaluate import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.Field import kotlin.test.Test import kotlin.test.assertEquals internal class ParserPrecedenceTest { - private val f: Field = DoubleField - @Test fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath())) @@ -37,4 +30,8 @@ internal class ParserPrecedenceTest { @Test fun test8(): Unit = assertEquals(18.0, f.evaluate("2*2^3+2".parseMath())) + + private companion object { + private val f = DoubleField + } } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt similarity index 67% rename from kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt index 53afaa674..13f5b3290 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt @@ -1,37 +1,24 @@ -/* - * 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.ast +package space.kscisnce.kmath.ast +import space.kscience.kmath.ast.parseMath import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.ComplexField -import space.kscience.kmath.expressions.MstField import space.kscience.kmath.expressions.evaluate -import space.kscience.kmath.expressions.interpret import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals internal class ParserTest { @Test - fun `evaluate MST`() { + fun evaluateParsedMst() { val mst = "2+2*(2+2)".parseMath() val res = ComplexField.evaluate(mst) assertEquals(Complex(10.0, 0.0), res) } @Test - fun `evaluate MSTExpression`() { - val res = MstField.invoke { number(2) + number(2) * (number(2) + number(2)) }.interpret(ComplexField) - assertEquals(Complex(10.0, 0.0), res) - } - - @Test - fun `evaluate MST with singular`() { + fun evaluateMstSymbol() { val mst = "i".parseMath() val res = ComplexField.evaluate(mst) assertEquals(ComplexField.i, res) @@ -39,14 +26,14 @@ internal class ParserTest { @Test - fun `evaluate MST with unary function`() { + fun evaluateMstUnary() { val mst = "sin(0)".parseMath() val res = DoubleField.evaluate(mst) assertEquals(0.0, res) } @Test - fun `evaluate MST with binary function`() { + fun evaluateMstBinary() { val magicalAlgebra = object : Algebra { override fun bindSymbolOrNull(value: String): String = value diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt index 83914f3ec..40468f5ab 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt @@ -6,11 +6,11 @@ package space.kscience.kmath.estree import space.kscience.kmath.estree.internal.ESTreeBuilder -import space.kscience.kmath.estree.internal.estree.BaseExpression import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MST.* import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.internal.estree.BaseExpression import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.NumericAlgebra diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt index 6f917a24c..ac20484a4 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -5,9 +5,14 @@ package space.kscience.kmath.estree.internal -import space.kscience.kmath.estree.internal.astring.generate -import space.kscience.kmath.estree.internal.estree.* import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.internal.astring.generate +import space.kscience.kmath.internal.estree.* +import space.kscience.kmath.internal.estree.BaseExpression +import space.kscience.kmath.internal.estree.BlockStatement +import space.kscience.kmath.internal.estree.Program +import space.kscience.kmath.internal.estree.VariableDeclaration +import space.kscience.kmath.internal.estree.VariableDeclarator import space.kscience.kmath.misc.Symbol internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExpression) { diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/stream/stream.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/stream/stream.kt deleted file mode 100644 index 4bdeeea0b..000000000 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/stream/stream.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.estree.internal.stream - -import space.kscience.kmath.estree.internal.emitter.Emitter - -internal open external class Stream : Emitter { - open fun pipe(dest: Any, options: Any): Any -} diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt similarity index 90% rename from kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.kt rename to kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt index 354757b83..cca2d83af 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt @@ -6,9 +6,9 @@ @file:JsModule("astring") @file:JsNonModule -package space.kscience.kmath.estree.internal.astring +package space.kscience.kmath.internal.astring -import space.kscience.kmath.estree.internal.estree.BaseNode +import space.kscience.kmath.internal.estree.BaseNode internal external interface Options { var indent: String? diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt new file mode 100644 index 000000000..1f6a5f04d --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt @@ -0,0 +1,3 @@ +package space.kscience.kmath.internal.astring + +internal typealias Generator = Any diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt new file mode 100644 index 000000000..a0c7cb6ee --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt @@ -0,0 +1,49 @@ +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", + "OVERRIDING_FINAL_MEMBER", + "RETURN_TYPE_MISMATCH_ON_OVERRIDE", + "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", + "ObjectPropertyName", + "ClassName", +) +@file:JsNonModule +@file:JsModule("js-base64") + +package space.kscience.kmath.internal.base64 + +import org.khronos.webgl.Uint8Array + +internal external var version: Any + +internal external var VERSION: Any + +internal external var btoaPolyfill: (bin: String) -> String + +internal external var _btoa: (bin: String) -> String + +internal external var fromUint8Array: (u8a: Uint8Array, urlsafe: Boolean) -> String + +internal external var utob: (u: String) -> String + +internal external var encode: (src: String, urlsafe: Boolean) -> String + +internal external var encodeURI: (src: String) -> String + +internal external var btou: (b: String) -> String + +internal external var atobPolyfill: (asc: String) -> String + +internal external var _atob: (asc: String) -> String + +internal external var toUint8Array: (a: String) -> Uint8Array + +internal external var decode: (src: String) -> String + +internal external var isValid: (src: Any) -> Boolean + +internal external var extendString: () -> Unit + +internal external var extendUint8Array: () -> Unit + +internal external var extendBuiltins: () -> Unit diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt new file mode 100644 index 000000000..d3e3539c6 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt @@ -0,0 +1,2234 @@ +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", + "OVERRIDING_FINAL_MEMBER", + "RETURN_TYPE_MISMATCH_ON_OVERRIDE", + "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", + "PropertyName", + "ClassName", +) + +@file:JsModule("binaryen") +@file:JsNonModule + +package space.kscience.kmath.internal.binaryen + +import org.khronos.webgl.Uint8Array +import kotlin.js.Promise + +internal external var isReady: Boolean + +internal external var ready: Promise + +internal external var none: Type + +internal external var i32: Type + +internal external var i64: Type + +internal external var f32: Type + +internal external var f64: Type + +internal external var v128: Type + +internal external var funcref: Type + +internal external var anyref: Type + +internal external var nullref: Type + +internal external var exnref: Type + +internal external var unreachable: Type + +internal external var auto: Type + +internal external fun createType(types: Array): Type + +internal external fun expandType(type: Type): Array + +internal external enum class ExpressionIds { + Invalid, + Block, + If, + Loop, + Break, + Switch, + Call, + CallIndirect, + LocalGet, + LocalSet, + GlobalGet, + GlobalSet, + Load, + Store, + Const, + Unary, + Binary, + Select, + Drop, + Return, + Host, + Nop, + Unreachable, + AtomicCmpxchg, + AtomicRMW, + AtomicWait, + AtomicNotify, + AtomicFence, + SIMDExtract, + SIMDReplace, + SIMDShuffle, + SIMDTernary, + SIMDShift, + SIMDLoad, + MemoryInit, + DataDrop, + MemoryCopy, + MemoryFill, + RefNull, + RefIsNull, + RefFunc, + Try, + Throw, + Rethrow, + BrOnExn, + TupleMake, + TupleExtract, + Push, + Pop +} + +internal external var InvalidId: ExpressionIds + +internal external var BlockId: ExpressionIds + +internal external var IfId: ExpressionIds + +internal external var LoopId: ExpressionIds + +internal external var BreakId: ExpressionIds + +internal external var SwitchId: ExpressionIds + +internal external var CallId: ExpressionIds + +internal external var CallIndirectId: ExpressionIds + +internal external var LocalGetId: ExpressionIds + +internal external var LocalSetId: ExpressionIds + +internal external var GlobalGetId: ExpressionIds + +internal external var GlobalSetId: ExpressionIds + +internal external var LoadId: ExpressionIds + +internal external var StoreId: ExpressionIds + +internal external var ConstId: ExpressionIds + +internal external var UnaryId: ExpressionIds + +internal external var BinaryId: ExpressionIds + +internal external var SelectId: ExpressionIds + +internal external var DropId: ExpressionIds + +internal external var ReturnId: ExpressionIds + +internal external var HostId: ExpressionIds + +internal external var NopId: ExpressionIds + +internal external var UnreachableId: ExpressionIds + +internal external var AtomicCmpxchgId: ExpressionIds + +internal external var AtomicRMWId: ExpressionIds + +internal external var AtomicWaitId: ExpressionIds + +internal external var AtomicNotifyId: ExpressionIds + +internal external var AtomicFenceId: ExpressionIds + +internal external var SIMDExtractId: ExpressionIds + +internal external var SIMDReplaceId: ExpressionIds + +internal external var SIMDShuffleId: ExpressionIds + +internal external var SIMDTernaryId: ExpressionIds + +internal external var SIMDShiftId: ExpressionIds + +internal external var SIMDLoadId: ExpressionIds + +internal external var MemoryInitId: ExpressionIds + +internal external var DataDropId: ExpressionIds + +internal external var MemoryCopyId: ExpressionIds + +internal external var MemoryFillId: ExpressionIds + +internal external var RefNullId: ExpressionIds + +internal external var RefIsNullId: ExpressionIds + +internal external var RefFuncId: ExpressionIds + +internal external var TryId: ExpressionIds + +internal external var ThrowId: ExpressionIds + +internal external var RethrowId: ExpressionIds + +internal external var BrOnExnId: ExpressionIds + +internal external var TupleMakeId: ExpressionIds + +internal external var TupleExtractId: ExpressionIds + +internal external var PushId: ExpressionIds + +internal external var PopId: ExpressionIds + +internal external enum class ExternalKinds { + Function, + Table, + Memory, + Global, + Event +} + +internal external var ExternalFunction: ExternalKinds + +internal external var ExternalTable: ExternalKinds + +internal external var ExternalMemory: ExternalKinds + +internal external var ExternalGlobal: ExternalKinds + +internal external var ExternalEvent: ExternalKinds + +internal external enum class Features { + MVP, + Atomics, + MutableGlobals, + TruncSat, + SIMD, + BulkMemory, + SignExt, + ExceptionHandling, + TailCall, + ReferenceTypes, + Multivalue, + GC, + Memory64, + All +} + +internal external enum class Operations { + ClzInt32, + CtzInt32, + PopcntInt32, + NegFloat32, + AbsFloat32, + CeilFloat32, + FloorFloat32, + TruncFloat32, + NearestFloat32, + SqrtFloat32, + EqZInt32, + ClzInt64, + CtzInt64, + PopcntInt64, + NegFloat64, + AbsFloat64, + CeilFloat64, + FloorFloat64, + TruncFloat64, + NearestFloat64, + SqrtFloat64, + EqZInt64, + ExtendSInt32, + ExtendUInt32, + WrapInt64, + TruncSFloat32ToInt32, + TruncSFloat32ToInt64, + TruncUFloat32ToInt32, + TruncUFloat32ToInt64, + TruncSFloat64ToInt32, + TruncSFloat64ToInt64, + TruncUFloat64ToInt32, + TruncUFloat64ToInt64, + TruncSatSFloat32ToInt32, + TruncSatSFloat32ToInt64, + TruncSatUFloat32ToInt32, + TruncSatUFloat32ToInt64, + TruncSatSFloat64ToInt32, + TruncSatSFloat64ToInt64, + TruncSatUFloat64ToInt32, + TruncSatUFloat64ToInt64, + ReinterpretFloat32, + ReinterpretFloat64, + ConvertSInt32ToFloat32, + ConvertSInt32ToFloat64, + ConvertUInt32ToFloat32, + ConvertUInt32ToFloat64, + ConvertSInt64ToFloat32, + ConvertSInt64ToFloat64, + ConvertUInt64ToFloat32, + ConvertUInt64ToFloat64, + PromoteFloat32, + DemoteFloat64, + ReinterpretInt32, + ReinterpretInt64, + ExtendS8Int32, + ExtendS16Int32, + ExtendS8Int64, + ExtendS16Int64, + ExtendS32Int64, + AddInt32, + SubInt32, + MulInt32, + DivSInt32, + DivUInt32, + RemSInt32, + RemUInt32, + AndInt32, + OrInt32, + XorInt32, + ShlInt32, + ShrUInt32, + ShrSInt32, + RotLInt32, + RotRInt32, + EqInt32, + NeInt32, + LtSInt32, + LtUInt32, + LeSInt32, + LeUInt32, + GtSInt32, + GtUInt32, + GeSInt32, + GeUInt32, + AddInt64, + SubInt64, + MulInt64, + DivSInt64, + DivUInt64, + RemSInt64, + RemUInt64, + AndInt64, + OrInt64, + XorInt64, + ShlInt64, + ShrUInt64, + ShrSInt64, + RotLInt64, + RotRInt64, + EqInt64, + NeInt64, + LtSInt64, + LtUInt64, + LeSInt64, + LeUInt64, + GtSInt64, + GtUInt64, + GeSInt64, + GeUInt64, + AddFloat32, + SubFloat32, + MulFloat32, + DivFloat32, + CopySignFloat32, + MinFloat32, + MaxFloat32, + EqFloat32, + NeFloat32, + LtFloat32, + LeFloat32, + GtFloat32, + GeFloat32, + AddFloat64, + SubFloat64, + MulFloat64, + DivFloat64, + CopySignFloat64, + MinFloat64, + MaxFloat64, + EqFloat64, + NeFloat64, + LtFloat64, + LeFloat64, + GtFloat64, + GeFloat64, + MemorySize, + MemoryGrow, + AtomicRMWAdd, + AtomicRMWSub, + AtomicRMWAnd, + AtomicRMWOr, + AtomicRMWXor, + AtomicRMWXchg, + SplatVecI8x16, + ExtractLaneSVecI8x16, + ExtractLaneUVecI8x16, + ReplaceLaneVecI8x16, + SplatVecI16x8, + ExtractLaneSVecI16x8, + ExtractLaneUVecI16x8, + ReplaceLaneVecI16x8, + SplatVecI32x4, + ExtractLaneVecI32x4, + ReplaceLaneVecI32x4, + SplatVecI64x2, + ExtractLaneVecI64x2, + ReplaceLaneVecI64x2, + SplatVecF32x4, + ExtractLaneVecF32x4, + ReplaceLaneVecF32x4, + SplatVecF64x2, + ExtractLaneVecF64x2, + ReplaceLaneVecF64x2, + EqVecI8x16, + NeVecI8x16, + LtSVecI8x16, + LtUVecI8x16, + GtSVecI8x16, + GtUVecI8x16, + LeSVecI8x16, + LeUVecI8x16, + GeSVecI8x16, + GeUVecI8x16, + EqVecI16x8, + NeVecI16x8, + LtSVecI16x8, + LtUVecI16x8, + GtSVecI16x8, + GtUVecI16x8, + LeSVecI16x8, + LeUVecI16x8, + GeSVecI16x8, + GeUVecI16x8, + EqVecI32x4, + NeVecI32x4, + LtSVecI32x4, + LtUVecI32x4, + GtSVecI32x4, + GtUVecI32x4, + LeSVecI32x4, + LeUVecI32x4, + GeSVecI32x4, + GeUVecI32x4, + EqVecF32x4, + NeVecF32x4, + LtVecF32x4, + GtVecF32x4, + LeVecF32x4, + GeVecF32x4, + EqVecF64x2, + NeVecF64x2, + LtVecF64x2, + GtVecF64x2, + LeVecF64x2, + GeVecF64x2, + NotVec128, + AndVec128, + OrVec128, + XorVec128, + AndNotVec128, + BitselectVec128, + NegVecI8x16, + AnyTrueVecI8x16, + AllTrueVecI8x16, + ShlVecI8x16, + ShrSVecI8x16, + ShrUVecI8x16, + AddVecI8x16, + AddSatSVecI8x16, + AddSatUVecI8x16, + SubVecI8x16, + SubSatSVecI8x16, + SubSatUVecI8x16, + MulVecI8x16, + MinSVecI8x16, + MinUVecI8x16, + MaxSVecI8x16, + MaxUVecI8x16, + NegVecI16x8, + AnyTrueVecI16x8, + AllTrueVecI16x8, + ShlVecI16x8, + ShrSVecI16x8, + ShrUVecI16x8, + AddVecI16x8, + AddSatSVecI16x8, + AddSatUVecI16x8, + SubVecI16x8, + SubSatSVecI16x8, + SubSatUVecI16x8, + MulVecI16x8, + MinSVecI16x8, + MinUVecI16x8, + MaxSVecI16x8, + MaxUVecI16x8, + DotSVecI16x8ToVecI32x4, + NegVecI32x4, + AnyTrueVecI32x4, + AllTrueVecI32x4, + ShlVecI32x4, + ShrSVecI32x4, + ShrUVecI32x4, + AddVecI32x4, + SubVecI32x4, + MulVecI32x4, + MinSVecI32x4, + MinUVecI32x4, + MaxSVecI32x4, + MaxUVecI32x4, + NegVecI64x2, + AnyTrueVecI64x2, + AllTrueVecI64x2, + ShlVecI64x2, + ShrSVecI64x2, + ShrUVecI64x2, + AddVecI64x2, + SubVecI64x2, + AbsVecF32x4, + NegVecF32x4, + SqrtVecF32x4, + QFMAVecF32x4, + QFMSVecF32x4, + AddVecF32x4, + SubVecF32x4, + MulVecF32x4, + DivVecF32x4, + MinVecF32x4, + MaxVecF32x4, + AbsVecF64x2, + NegVecF64x2, + SqrtVecF64x2, + QFMAVecF64x2, + QFMSVecF64x2, + AddVecF64x2, + SubVecF64x2, + MulVecF64x2, + DivVecF64x2, + MinVecF64x2, + MaxVecF64x2, + TruncSatSVecF32x4ToVecI32x4, + TruncSatUVecF32x4ToVecI32x4, + TruncSatSVecF64x2ToVecI64x2, + TruncSatUVecF64x2ToVecI64x2, + ConvertSVecI32x4ToVecF32x4, + ConvertUVecI32x4ToVecF32x4, + ConvertSVecI64x2ToVecF64x2, + ConvertUVecI64x2ToVecF64x2, + LoadSplatVec8x16, + LoadSplatVec16x8, + LoadSplatVec32x4, + LoadSplatVec64x2, + LoadExtSVec8x8ToVecI16x8, + LoadExtUVec8x8ToVecI16x8, + LoadExtSVec16x4ToVecI32x4, + LoadExtUVec16x4ToVecI32x4, + LoadExtSVec32x2ToVecI64x2, + LoadExtUVec32x2ToVecI64x2, + NarrowSVecI16x8ToVecI8x16, + NarrowUVecI16x8ToVecI8x16, + NarrowSVecI32x4ToVecI16x8, + NarrowUVecI32x4ToVecI16x8, + WidenLowSVecI8x16ToVecI16x8, + WidenHighSVecI8x16ToVecI16x8, + WidenLowUVecI8x16ToVecI16x8, + WidenHighUVecI8x16ToVecI16x8, + WidenLowSVecI16x8ToVecI32x4, + WidenHighSVecI16x8ToVecI32x4, + WidenLowUVecI16x8ToVecI32x4, + WidenHighUVecI16x8ToVecI32x4, + SwizzleVec8x16 +} + +internal external var ClzInt32: Operations + +internal external var CtzInt32: Operations + +internal external var PopcntInt32: Operations + +internal external var NegFloat32: Operations + +internal external var AbsFloat32: Operations + +internal external var CeilFloat32: Operations + +internal external var FloorFloat32: Operations + +internal external var TruncFloat32: Operations + +internal external var NearestFloat32: Operations + +internal external var SqrtFloat32: Operations + +internal external var EqZInt32: Operations + +internal external var ClzInt64: Operations + +internal external var CtzInt64: Operations + +internal external var PopcntInt64: Operations + +internal external var NegFloat64: Operations + +internal external var AbsFloat64: Operations + +internal external var CeilFloat64: Operations + +internal external var FloorFloat64: Operations + +internal external var TruncFloat64: Operations + +internal external var NearestFloat64: Operations + +internal external var SqrtFloat64: Operations + +internal external var EqZInt64: Operations + +internal external var ExtendSInt32: Operations + +internal external var ExtendUInt32: Operations + +internal external var WrapInt64: Operations + +internal external var TruncSFloat32ToInt32: Operations + +internal external var TruncSFloat32ToInt64: Operations + +internal external var TruncUFloat32ToInt32: Operations + +internal external var TruncUFloat32ToInt64: Operations + +internal external var TruncSFloat64ToInt32: Operations + +internal external var TruncSFloat64ToInt64: Operations + +internal external var TruncUFloat64ToInt32: Operations + +internal external var TruncUFloat64ToInt64: Operations + +internal external var TruncSatSFloat32ToInt32: Operations + +internal external var TruncSatSFloat32ToInt64: Operations + +internal external var TruncSatUFloat32ToInt32: Operations + +internal external var TruncSatUFloat32ToInt64: Operations + +internal external var TruncSatSFloat64ToInt32: Operations + +internal external var TruncSatSFloat64ToInt64: Operations + +internal external var TruncSatUFloat64ToInt32: Operations + +internal external var TruncSatUFloat64ToInt64: Operations + +internal external var ReinterpretFloat32: Operations + +internal external var ReinterpretFloat64: Operations + +internal external var ConvertSInt32ToFloat32: Operations + +internal external var ConvertSInt32ToFloat64: Operations + +internal external var ConvertUInt32ToFloat32: Operations + +internal external var ConvertUInt32ToFloat64: Operations + +internal external var ConvertSInt64ToFloat32: Operations + +internal external var ConvertSInt64ToFloat64: Operations + +internal external var ConvertUInt64ToFloat32: Operations + +internal external var ConvertUInt64ToFloat64: Operations + +internal external var PromoteFloat32: Operations + +internal external var DemoteFloat64: Operations + +internal external var ReinterpretInt32: Operations + +internal external var ReinterpretInt64: Operations + +internal external var ExtendS8Int32: Operations + +internal external var ExtendS16Int32: Operations + +internal external var ExtendS8Int64: Operations + +internal external var ExtendS16Int64: Operations + +internal external var ExtendS32Int64: Operations + +internal external var AddInt32: Operations + +internal external var SubInt32: Operations + +internal external var MulInt32: Operations + +internal external var DivSInt32: Operations + +internal external var DivUInt32: Operations + +internal external var RemSInt32: Operations + +internal external var RemUInt32: Operations + +internal external var AndInt32: Operations + +internal external var OrInt32: Operations + +internal external var XorInt32: Operations + +internal external var ShlInt32: Operations + +internal external var ShrUInt32: Operations + +internal external var ShrSInt32: Operations + +internal external var RotLInt32: Operations + +internal external var RotRInt32: Operations + +internal external var EqInt32: Operations + +internal external var NeInt32: Operations + +internal external var LtSInt32: Operations + +internal external var LtUInt32: Operations + +internal external var LeSInt32: Operations + +internal external var LeUInt32: Operations + +internal external var GtSInt32: Operations + +internal external var GtUInt32: Operations + +internal external var GeSInt32: Operations + +internal external var GeUInt32: Operations + +internal external var AddInt64: Operations + +internal external var SubInt64: Operations + +internal external var MulInt64: Operations + +internal external var DivSInt64: Operations + +internal external var DivUInt64: Operations + +internal external var RemSInt64: Operations + +internal external var RemUInt64: Operations + +internal external var AndInt64: Operations + +internal external var OrInt64: Operations + +internal external var XorInt64: Operations + +internal external var ShlInt64: Operations + +internal external var ShrUInt64: Operations + +internal external var ShrSInt64: Operations + +internal external var RotLInt64: Operations + +internal external var RotRInt64: Operations + +internal external var EqInt64: Operations + +internal external var NeInt64: Operations + +internal external var LtSInt64: Operations + +internal external var LtUInt64: Operations + +internal external var LeSInt64: Operations + +internal external var LeUInt64: Operations + +internal external var GtSInt64: Operations + +internal external var GtUInt64: Operations + +internal external var GeSInt64: Operations + +internal external var GeUInt64: Operations + +internal external var AddFloat32: Operations + +internal external var SubFloat32: Operations + +internal external var MulFloat32: Operations + +internal external var DivFloat32: Operations + +internal external var CopySignFloat32: Operations + +internal external var MinFloat32: Operations + +internal external var MaxFloat32: Operations + +internal external var EqFloat32: Operations + +internal external var NeFloat32: Operations + +internal external var LtFloat32: Operations + +internal external var LeFloat32: Operations + +internal external var GtFloat32: Operations + +internal external var GeFloat32: Operations + +internal external var AddFloat64: Operations + +internal external var SubFloat64: Operations + +internal external var MulFloat64: Operations + +internal external var DivFloat64: Operations + +internal external var CopySignFloat64: Operations + +internal external var MinFloat64: Operations + +internal external var MaxFloat64: Operations + +internal external var EqFloat64: Operations + +internal external var NeFloat64: Operations + +internal external var LtFloat64: Operations + +internal external var LeFloat64: Operations + +internal external var GtFloat64: Operations + +internal external var GeFloat64: Operations + +internal external var MemorySize: Operations + +internal external var MemoryGrow: Operations + +internal external var AtomicRMWAdd: Operations + +internal external var AtomicRMWSub: Operations + +internal external var AtomicRMWAnd: Operations + +internal external var AtomicRMWOr: Operations + +internal external var AtomicRMWXor: Operations + +internal external var AtomicRMWXchg: Operations + +internal external var SplatVecI8x16: Operations + +internal external var ExtractLaneSVecI8x16: Operations + +internal external var ExtractLaneUVecI8x16: Operations + +internal external var ReplaceLaneVecI8x16: Operations + +internal external var SplatVecI16x8: Operations + +internal external var ExtractLaneSVecI16x8: Operations + +internal external var ExtractLaneUVecI16x8: Operations + +internal external var ReplaceLaneVecI16x8: Operations + +internal external var SplatVecI32x4: Operations + +internal external var ExtractLaneVecI32x4: Operations + +internal external var ReplaceLaneVecI32x4: Operations + +internal external var SplatVecI64x2: Operations + +internal external var ExtractLaneVecI64x2: Operations + +internal external var ReplaceLaneVecI64x2: Operations + +internal external var SplatVecF32x4: Operations + +internal external var ExtractLaneVecF32x4: Operations + +internal external var ReplaceLaneVecF32x4: Operations + +internal external var SplatVecF64x2: Operations + +internal external var ExtractLaneVecF64x2: Operations + +internal external var ReplaceLaneVecF64x2: Operations + +internal external var EqVecI8x16: Operations + +internal external var NeVecI8x16: Operations + +internal external var LtSVecI8x16: Operations + +internal external var LtUVecI8x16: Operations + +internal external var GtSVecI8x16: Operations + +internal external var GtUVecI8x16: Operations + +internal external var LeSVecI8x16: Operations + +internal external var LeUVecI8x16: Operations + +internal external var GeSVecI8x16: Operations + +internal external var GeUVecI8x16: Operations + +internal external var EqVecI16x8: Operations + +internal external var NeVecI16x8: Operations + +internal external var LtSVecI16x8: Operations + +internal external var LtUVecI16x8: Operations + +internal external var GtSVecI16x8: Operations + +internal external var GtUVecI16x8: Operations + +internal external var LeSVecI16x8: Operations + +internal external var LeUVecI16x8: Operations + +internal external var GeSVecI16x8: Operations + +internal external var GeUVecI16x8: Operations + +internal external var EqVecI32x4: Operations + +internal external var NeVecI32x4: Operations + +internal external var LtSVecI32x4: Operations + +internal external var LtUVecI32x4: Operations + +internal external var GtSVecI32x4: Operations + +internal external var GtUVecI32x4: Operations + +internal external var LeSVecI32x4: Operations + +internal external var LeUVecI32x4: Operations + +internal external var GeSVecI32x4: Operations + +internal external var GeUVecI32x4: Operations + +internal external var EqVecF32x4: Operations + +internal external var NeVecF32x4: Operations + +internal external var LtVecF32x4: Operations + +internal external var GtVecF32x4: Operations + +internal external var LeVecF32x4: Operations + +internal external var GeVecF32x4: Operations + +internal external var EqVecF64x2: Operations + +internal external var NeVecF64x2: Operations + +internal external var LtVecF64x2: Operations + +internal external var GtVecF64x2: Operations + +internal external var LeVecF64x2: Operations + +internal external var GeVecF64x2: Operations + +internal external var NotVec128: Operations + +internal external var AndVec128: Operations + +internal external var OrVec128: Operations + +internal external var XorVec128: Operations + +internal external var AndNotVec128: Operations + +internal external var BitselectVec128: Operations + +internal external var NegVecI8x16: Operations + +internal external var AnyTrueVecI8x16: Operations + +internal external var AllTrueVecI8x16: Operations + +internal external var ShlVecI8x16: Operations + +internal external var ShrSVecI8x16: Operations + +internal external var ShrUVecI8x16: Operations + +internal external var AddVecI8x16: Operations + +internal external var AddSatSVecI8x16: Operations + +internal external var AddSatUVecI8x16: Operations + +internal external var SubVecI8x16: Operations + +internal external var SubSatSVecI8x16: Operations + +internal external var SubSatUVecI8x16: Operations + +internal external var MulVecI8x16: Operations + +internal external var MinSVecI8x16: Operations + +internal external var MinUVecI8x16: Operations + +internal external var MaxSVecI8x16: Operations + +internal external var MaxUVecI8x16: Operations + +internal external var NegVecI16x8: Operations + +internal external var AnyTrueVecI16x8: Operations + +internal external var AllTrueVecI16x8: Operations + +internal external var ShlVecI16x8: Operations + +internal external var ShrSVecI16x8: Operations + +internal external var ShrUVecI16x8: Operations + +internal external var AddVecI16x8: Operations + +internal external var AddSatSVecI16x8: Operations + +internal external var AddSatUVecI16x8: Operations + +internal external var SubVecI16x8: Operations + +internal external var SubSatSVecI16x8: Operations + +internal external var SubSatUVecI16x8: Operations + +internal external var MulVecI16x8: Operations + +internal external var MinSVecI16x8: Operations + +internal external var MinUVecI16x8: Operations + +internal external var MaxSVecI16x8: Operations + +internal external var MaxUVecI16x8: Operations + +internal external var DotSVecI16x8ToVecI32x4: Operations + +internal external var NegVecI32x4: Operations + +internal external var AnyTrueVecI32x4: Operations + +internal external var AllTrueVecI32x4: Operations + +internal external var ShlVecI32x4: Operations + +internal external var ShrSVecI32x4: Operations + +internal external var ShrUVecI32x4: Operations + +internal external var AddVecI32x4: Operations + +internal external var SubVecI32x4: Operations + +internal external var MulVecI32x4: Operations + +internal external var MinSVecI32x4: Operations + +internal external var MinUVecI32x4: Operations + +internal external var MaxSVecI32x4: Operations + +internal external var MaxUVecI32x4: Operations + +internal external var NegVecI64x2: Operations + +internal external var AnyTrueVecI64x2: Operations + +internal external var AllTrueVecI64x2: Operations + +internal external var ShlVecI64x2: Operations + +internal external var ShrSVecI64x2: Operations + +internal external var ShrUVecI64x2: Operations + +internal external var AddVecI64x2: Operations + +internal external var SubVecI64x2: Operations + +internal external var AbsVecF32x4: Operations + +internal external var NegVecF32x4: Operations + +internal external var SqrtVecF32x4: Operations + +internal external var QFMAVecF32x4: Operations + +internal external var QFMSVecF32x4: Operations + +internal external var AddVecF32x4: Operations + +internal external var SubVecF32x4: Operations + +internal external var MulVecF32x4: Operations + +internal external var DivVecF32x4: Operations + +internal external var MinVecF32x4: Operations + +internal external var MaxVecF32x4: Operations + +internal external var AbsVecF64x2: Operations + +internal external var NegVecF64x2: Operations + +internal external var SqrtVecF64x2: Operations + +internal external var QFMAVecF64x2: Operations + +internal external var QFMSVecF64x2: Operations + +internal external var AddVecF64x2: Operations + +internal external var SubVecF64x2: Operations + +internal external var MulVecF64x2: Operations + +internal external var DivVecF64x2: Operations + +internal external var MinVecF64x2: Operations + +internal external var MaxVecF64x2: Operations + +internal external var TruncSatSVecF32x4ToVecI32x4: Operations + +internal external var TruncSatUVecF32x4ToVecI32x4: Operations + +internal external var TruncSatSVecF64x2ToVecI64x2: Operations + +internal external var TruncSatUVecF64x2ToVecI64x2: Operations + +internal external var ConvertSVecI32x4ToVecF32x4: Operations + +internal external var ConvertUVecI32x4ToVecF32x4: Operations + +internal external var ConvertSVecI64x2ToVecF64x2: Operations + +internal external var ConvertUVecI64x2ToVecF64x2: Operations + +internal external var LoadSplatVec8x16: Operations + +internal external var LoadSplatVec16x8: Operations + +internal external var LoadSplatVec32x4: Operations + +internal external var LoadSplatVec64x2: Operations + +internal external var LoadExtSVec8x8ToVecI16x8: Operations + +internal external var LoadExtUVec8x8ToVecI16x8: Operations + +internal external var LoadExtSVec16x4ToVecI32x4: Operations + +internal external var LoadExtUVec16x4ToVecI32x4: Operations + +internal external var LoadExtSVec32x2ToVecI64x2: Operations + +internal external var LoadExtUVec32x2ToVecI64x2: Operations + +internal external var NarrowSVecI16x8ToVecI8x16: Operations + +internal external var NarrowUVecI16x8ToVecI8x16: Operations + +internal external var NarrowSVecI32x4ToVecI16x8: Operations + +internal external var NarrowUVecI32x4ToVecI16x8: Operations + +internal external var WidenLowSVecI8x16ToVecI16x8: Operations + +internal external var WidenHighSVecI8x16ToVecI16x8: Operations + +internal external var WidenLowUVecI8x16ToVecI16x8: Operations + +internal external var WidenHighUVecI8x16ToVecI16x8: Operations + +internal external var WidenLowSVecI16x8ToVecI32x4: Operations + +internal external var WidenHighSVecI16x8ToVecI32x4: Operations + +internal external var WidenLowUVecI16x8ToVecI32x4: Operations + +internal external var WidenHighUVecI16x8ToVecI32x4: Operations + +internal external var SwizzleVec8x16: Operations + +internal external interface `T$2` { + fun get(index: Number, type: Type): ExpressionRef + fun set(index: Number, value: ExpressionRef): ExpressionRef + fun tee(index: Number, value: ExpressionRef, type: Type): ExpressionRef +} + +internal external interface `T$3` { + fun get(name: String, type: Type): ExpressionRef + fun set(name: String, value: ExpressionRef): ExpressionRef +} + +internal external interface `T$4` { + fun size(): ExpressionRef + fun grow(value: ExpressionRef): ExpressionRef + fun init(segment: Number, dest: ExpressionRef, offset: ExpressionRef, size: ExpressionRef): ExpressionRef + fun copy(dest: ExpressionRef, source: ExpressionRef, size: ExpressionRef): ExpressionRef + fun fill(dest: ExpressionRef, value: ExpressionRef, size: ExpressionRef): ExpressionRef +} + +internal external interface `T$5` { + fun drop(segment: Number): ExpressionRef +} + +internal external interface `T$6` { + fun f32(value: ExpressionRef): ExpressionRef + fun f64(value: ExpressionRef): ExpressionRef +} + +internal external interface `T$7` { + fun add(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun sub(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun and(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun or(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun xor(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun xchg(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun cmpxchg(offset: Number, ptr: ExpressionRef, expected: ExpressionRef, replacement: ExpressionRef): ExpressionRef +} + +internal external interface `T$8` { + fun load(offset: Number, ptr: ExpressionRef): ExpressionRef + fun load8_u(offset: Number, ptr: ExpressionRef): ExpressionRef + fun load16_u(offset: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store8(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store16(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + var rmw: `T$7` + var rmw8_u: `T$7` + var rmw16_u: `T$7` + fun wait(ptr: ExpressionRef, expected: ExpressionRef, timeout: ExpressionRef): ExpressionRef +} + +internal external interface `T$9` { + fun load(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load8_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load8_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load16_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load16_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store8(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store16(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun const(value: Number): ExpressionRef + fun clz(value: ExpressionRef): ExpressionRef + fun ctz(value: ExpressionRef): ExpressionRef + fun popcnt(value: ExpressionRef): ExpressionRef + fun eqz(value: ExpressionRef): ExpressionRef + var trunc_s: `T$6` + var trunc_u: `T$6` + var trunc_s_sat: `T$6` + var trunc_u_sat: `T$6` + fun reinterpret(value: ExpressionRef): ExpressionRef + fun extend8_s(value: ExpressionRef): ExpressionRef + fun extend16_s(value: ExpressionRef): ExpressionRef + fun wrap(value: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rem_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rem_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun and(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun or(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun xor(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun shl(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun shr_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun shr_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rotl(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rotr(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + var atomic: `T$8` + fun pop(): ExpressionRef +} + +internal external interface `T$10` { + fun load(offset: Number, ptr: ExpressionRef): ExpressionRef + fun load8_u(offset: Number, ptr: ExpressionRef): ExpressionRef + fun load16_u(offset: Number, ptr: ExpressionRef): ExpressionRef + fun load32_u(offset: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store8(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store16(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store32(offset: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + var rmw: `T$7` + var rmw8_u: `T$7` + var rmw16_u: `T$7` + var rmw32_u: `T$7` + fun wait(ptr: ExpressionRef, expected: ExpressionRef, timeout: ExpressionRef): ExpressionRef +} + +internal external interface `T$11` { + fun load(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load8_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load8_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load16_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load16_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load32_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load32_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store8(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store16(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun store32(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun const(low: Number, high: Number): ExpressionRef + fun clz(value: ExpressionRef): ExpressionRef + fun ctz(value: ExpressionRef): ExpressionRef + fun popcnt(value: ExpressionRef): ExpressionRef + fun eqz(value: ExpressionRef): ExpressionRef + var trunc_s: `T$6` + var trunc_u: `T$6` + var trunc_s_sat: `T$6` + var trunc_u_sat: `T$6` + fun reinterpret(value: ExpressionRef): ExpressionRef + fun extend8_s(value: ExpressionRef): ExpressionRef + fun extend16_s(value: ExpressionRef): ExpressionRef + fun extend32_s(value: ExpressionRef): ExpressionRef + fun extend_s(value: ExpressionRef): ExpressionRef + fun extend_u(value: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rem_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rem_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun and(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun or(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun xor(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun shl(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun shr_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun shr_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rotl(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun rotr(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + var atomic: `T$10` + fun pop(): ExpressionRef +} + +internal external interface `T$12` { + fun load(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun const(value: Number): ExpressionRef + fun const_bits(value: Number): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun abs(value: ExpressionRef): ExpressionRef + fun ceil(value: ExpressionRef): ExpressionRef + fun floor(value: ExpressionRef): ExpressionRef + fun trunc(value: ExpressionRef): ExpressionRef + fun nearest(value: ExpressionRef): ExpressionRef + fun sqrt(value: ExpressionRef): ExpressionRef + fun reinterpret(value: ExpressionRef): ExpressionRef + var convert_s: `T$6` + var convert_u: `T$6` + fun demote(value: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun copysign(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun pop(): ExpressionRef +} + +internal external interface `T$13` { + fun load(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun const(value: Number): ExpressionRef + fun const_bits(low: Number, high: Number): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun abs(value: ExpressionRef): ExpressionRef + fun ceil(value: ExpressionRef): ExpressionRef + fun floor(value: ExpressionRef): ExpressionRef + fun trunc(value: ExpressionRef): ExpressionRef + fun nearest(value: ExpressionRef): ExpressionRef + fun sqrt(value: ExpressionRef): ExpressionRef + fun reinterpret(value: ExpressionRef): ExpressionRef + var convert_s: `T$6` + var convert_u: `T$6` + fun promote(value: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun copysign(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun pop(): ExpressionRef +} + +internal external interface `T$14` { + fun load(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun store(offset: Number, align: Number, ptr: ExpressionRef, value: ExpressionRef): ExpressionRef + fun const(value: Number): ExpressionRef + fun not(value: ExpressionRef): ExpressionRef + fun and(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun or(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun xor(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun andnot(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun bitselect(left: ExpressionRef, right: ExpressionRef, cond: ExpressionRef): ExpressionRef + fun pop(): ExpressionRef +} + +internal external interface `T$15` { + fun splat(value: ExpressionRef): ExpressionRef + fun extract_lane_s(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun extract_lane_u(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun replace_lane(vec: ExpressionRef, index: ExpressionRef, value: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun any_true(value: ExpressionRef): ExpressionRef + fun all_true(value: ExpressionRef): ExpressionRef + fun shl(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_s(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_u(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun add_saturate_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun add_saturate_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub_saturate_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub_saturate_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun avgr_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun narrow_i16x8_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun narrow_i16x8_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef +} + +internal external interface `T$16` { + fun splat(value: ExpressionRef): ExpressionRef + fun extract_lane_s(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun extract_lane_u(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun replace_lane(vec: ExpressionRef, index: ExpressionRef, value: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun any_true(value: ExpressionRef): ExpressionRef + fun all_true(value: ExpressionRef): ExpressionRef + fun shl(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_s(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_u(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun add_saturate_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun add_saturate_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub_saturate_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub_saturate_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun avgr_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun narrow_i32x4_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun narrow_i32x4_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun widen_low_i8x16_s(value: ExpressionRef): ExpressionRef + fun widen_high_i8x16_s(value: ExpressionRef): ExpressionRef + fun widen_low_i8x16_u(value: ExpressionRef): ExpressionRef + fun widen_high_i8x16_u(value: ExpressionRef): ExpressionRef + fun load8x8_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load8x8_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef +} + +internal external interface `T$17` { + fun splat(value: ExpressionRef): ExpressionRef + fun extract_lane(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun replace_lane(vec: ExpressionRef, index: ExpressionRef, value: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_s(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge_u(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun any_true(value: ExpressionRef): ExpressionRef + fun all_true(value: ExpressionRef): ExpressionRef + fun shl(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_s(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_u(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun trunc_sat_f32x4_s(value: ExpressionRef): ExpressionRef + fun trunc_sat_f32x4_u(value: ExpressionRef): ExpressionRef + fun widen_low_i16x8_s(value: ExpressionRef): ExpressionRef + fun widen_high_i16x8_s(value: ExpressionRef): ExpressionRef + fun widen_low_i16x8_u(value: ExpressionRef): ExpressionRef + fun widen_high_i16x8_u(value: ExpressionRef): ExpressionRef + fun load16x4_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load16x4_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef +} + +internal external interface `T$18` { + fun splat(value: ExpressionRef): ExpressionRef + fun extract_lane(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun replace_lane(vec: ExpressionRef, index: ExpressionRef, value: ExpressionRef): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun any_true(value: ExpressionRef): ExpressionRef + fun all_true(value: ExpressionRef): ExpressionRef + fun shl(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_s(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun shr_u(vec: ExpressionRef, shift: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun trunc_sat_f64x2_s(value: ExpressionRef): ExpressionRef + fun trunc_sat_f64x2_u(value: ExpressionRef): ExpressionRef + fun load32x2_s(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef + fun load32x2_u(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef +} + +internal external interface `T$19` { + fun splat(value: ExpressionRef): ExpressionRef + fun extract_lane(vec: ExpressionRef, index: ExpressionRef): ExpressionRef + fun replace_lane(vec: ExpressionRef, index: ExpressionRef, value: ExpressionRef): ExpressionRef + fun eq(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ne(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun lt(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun gt(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun le(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun ge(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun abs(value: ExpressionRef): ExpressionRef + fun neg(value: ExpressionRef): ExpressionRef + fun sqrt(value: ExpressionRef): ExpressionRef + fun qfma(a: ExpressionRef, b: ExpressionRef, c: ExpressionRef): ExpressionRef + fun qfms(a: ExpressionRef, b: ExpressionRef, c: ExpressionRef): ExpressionRef + fun add(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun sub(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun mul(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun div(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun min(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun max(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun convert_i32x4_s(value: ExpressionRef): ExpressionRef + fun convert_i32x4_u(value: ExpressionRef): ExpressionRef +} + +internal external interface `T$20` { + fun shuffle(left: ExpressionRef, right: ExpressionRef, mask: Array): ExpressionRef + fun swizzle(left: ExpressionRef, right: ExpressionRef): ExpressionRef + fun load_splat(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef +} + +internal external interface `T$21` { + fun load_splat(offset: Number, align: Number, ptr: ExpressionRef): ExpressionRef +} + +internal external interface `T$22` { + fun pop(): ExpressionRef +} + +internal external interface `T$23` { + fun `null`(): ExpressionRef + fun is_null(value: ExpressionRef): ExpressionRef + fun func(name: String): ExpressionRef +} + +internal external interface `T$24` { + fun notify(ptr: ExpressionRef, notifyCount: ExpressionRef): ExpressionRef + fun fence(): ExpressionRef +} + +internal external interface `T$25` { + fun make(elements: Array): ExpressionRef + fun extract(tuple: ExpressionRef, index: Number): ExpressionRef +} + +internal external interface `T$26` { + var imported: Boolean + var segments: Array +} + +internal external interface `T$27` { + var binary: Uint8Array + var sourceMap: String? +} + +internal open external class Module { + open var ptr: Number + open fun block(label: String, children: Array, resultType: Type = definedExternally): ExpressionRef + open fun `if`( + condition: ExpressionRef, + ifTrue: ExpressionRef, + ifFalse: ExpressionRef = definedExternally + ): ExpressionRef + + open fun loop(label: String, body: ExpressionRef): ExpressionRef + open fun br( + label: String, + condition: ExpressionRef = definedExternally, + value: ExpressionRef = definedExternally + ): ExpressionRef + + open fun br_if( + label: String, + condition: ExpressionRef = definedExternally, + value: ExpressionRef = definedExternally + ): ExpressionRef + + open fun switch( + labels: Array, + defaultLabel: String, + condition: ExpressionRef, + value: ExpressionRef = definedExternally + ): ExpressionRef + + open fun call(name: String, operands: Array, returnType: Type): ExpressionRef + open fun return_call(name: String, operands: Array, returnType: Type): ExpressionRef + open fun call_indirect( + target: ExpressionRef, + operands: Array, + params: Type, + results: Type + ): ExpressionRef + + open fun return_call_indirect( + target: ExpressionRef, + operands: Array, + params: Type, + results: Type + ): ExpressionRef + + open var local: `T$2` + open var global: `T$3` + open var memory: `T$4` + open var data: `T$5` + open var i32: `T$9` + open var i64: `T$11` + open var f32: `T$12` + open var f64: `T$13` + open var v128: `T$14` + open var i8x16: `T$15` + open var i16x8: `T$16` + open var i32x4: `T$17` + open var i64x2: `T$18` + open var f32x4: `T$19` + open var f64x2: `T$19` + open var v8x16: `T$20` + open var v16x8: `T$21` + open var v32x4: `T$21` + open var v64x2: `T$21` + open var funcref: `T$22` + open var anyref: `T$22` + open var nullref: `T$22` + open var exnref: `T$22` + open var ref: `T$23` + open var atomic: `T$24` + open var tuple: `T$25` + open fun `try`(body: ExpressionRef, catchBody: ExpressionRef): ExpressionRef + open fun `throw`(event: String, operands: Array): ExpressionRef + open fun rethrow(exnref: ExpressionRef): ExpressionRef + open fun br_on_exn(label: String, event: String, exnref: ExpressionRef): ExpressionRef + open fun push(value: ExpressionRef): ExpressionRef + open fun select( + condition: ExpressionRef, + ifTrue: ExpressionRef, + ifFalse: ExpressionRef, + type: Type = definedExternally + ): ExpressionRef + + open fun drop(value: ExpressionRef): ExpressionRef + open fun `return`(value: ExpressionRef = definedExternally): ExpressionRef + open fun host(op: Operations, name: String, operands: Array): ExpressionRef + open fun nop(): ExpressionRef + open fun unreachable(): ExpressionRef + open fun addFunction(name: String, params: Type, results: Type, vars: Array, body: ExpressionRef): FunctionRef + open fun getFunction(name: String): FunctionRef + open fun removeFunction(name: String) + open fun getNumFunctions(): Number + open fun getFunctionByIndex(index: Number): FunctionRef + open fun addGlobal(name: String, type: Type, mutable: Boolean, init: ExpressionRef): GlobalRef + open fun getGlobal(name: String): GlobalRef + open fun removeGlobal(name: String) + open fun addEvent(name: String, attribute: Number, params: Type, results: Type): EventRef + open fun getEvent(name: String): EventRef + open fun removeEvent(name: String) + open fun addFunctionImport( + internalName: String, + externalModuleName: String, + externalBaseName: String, + params: Type, + results: Type + ) + + open fun addTableImport(internalName: String, externalModuleName: String, externalBaseName: String) + open fun addMemoryImport(internalName: String, externalModuleName: String, externalBaseName: String) + open fun addGlobalImport( + internalName: String, + externalModuleName: String, + externalBaseName: String, + globalType: Type + ) + + open fun addEventImport( + internalName: String, + externalModuleName: String, + externalBaseName: String, + attribute: Number, + params: Type, + results: Type + ) + + open fun addFunctionExport(internalName: String, externalName: String): ExportRef + open fun addTableExport(internalName: String, externalName: String): ExportRef + open fun addMemoryExport(internalName: String, externalName: String): ExportRef + open fun addGlobalExport(internalName: String, externalName: String): ExportRef + open fun removeExport(externalName: String) + open fun getNumExports(): Number + open fun getExportByIndex(index: Number): ExportRef + open fun setFunctionTable( + initial: Number, + maximum: Number, + funcNames: Array, + offset: ExpressionRef = definedExternally + ) + + open fun getFunctionTable(): `T$26` + open fun setMemory( + initial: Number, + maximum: Number, + exportName: String? = definedExternally, + segments: Array? = definedExternally, + flags: Array? = definedExternally, + shared: Boolean = definedExternally + ) + + open fun getNumMemorySegments(): Number + open fun getMemorySegmentInfoByIndex(index: Number): MemorySegmentInfo + open fun setStart(start: FunctionRef) + open fun getFeatures(): Features + open fun setFeatures(features: Features) + open fun addCustomSection(name: String, contents: Uint8Array) + open fun emitText(): String + open fun emitStackIR(optimize: Boolean = definedExternally): String + open fun emitAsmjs(): String + open fun validate(): Number + open fun optimize() + open fun optimizeFunction(func: String) + open fun optimizeFunction(func: FunctionRef) + open fun runPasses(passes: Array) + open fun runPassesOnFunction(func: String, passes: Array) + open fun runPassesOnFunction(func: FunctionRef, passes: Array) + open fun autoDrop() + open fun dispose() + open fun emitBinary(): Uint8Array + open fun emitBinary(sourceMapUrl: String?): `T$27` + open fun interpret() + open fun addDebugInfoFileName(filename: String): Number + open fun getDebugInfoFileName(index: Number): String? + open fun setDebugLocation( + func: FunctionRef, + expr: ExpressionRef, + fileIndex: Number, + lineNumber: Number, + columnNumber: Number + ) + + open fun copyExpression(expr: ExpressionRef): ExpressionRef +} + +internal external interface MemorySegment { + var offset: ExpressionRef + var data: Uint8Array + var passive: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +internal external interface TableElement { + var offset: ExpressionRef + var names: Array +} + +internal external fun wrapModule(ptr: Number): Module + +internal external fun getExpressionId(expression: ExpressionRef): Number + +internal external fun getExpressionType(expression: ExpressionRef): Type + +internal external fun getExpressionInfo(expression: ExpressionRef): ExpressionInfo + +internal external interface MemorySegmentInfo { + var offset: ExpressionRef + var data: Uint8Array + var passive: Boolean +} + +internal external interface ExpressionInfo { + var id: ExpressionIds + var type: Type +} + +internal external interface BlockInfo : ExpressionInfo { + var name: String + var children: Array +} + +internal external interface IfInfo : ExpressionInfo { + var condition: ExpressionRef + var ifTrue: ExpressionRef + var ifFalse: ExpressionRef +} + +internal external interface LoopInfo : ExpressionInfo { + var name: String + var body: ExpressionRef +} + +internal external interface BreakInfo : ExpressionInfo { + var name: String + var condition: ExpressionRef + var value: ExpressionRef +} + +internal external interface SwitchInfo : ExpressionInfo { + var names: Array + var defaultName: String? + var condition: ExpressionRef + var value: ExpressionRef +} + +internal external interface CallInfo : ExpressionInfo { + var isReturn: Boolean + var target: String + var operands: Array +} + +internal external interface CallIndirectInfo : ExpressionInfo { + var isReturn: Boolean + var target: ExpressionRef + var operands: Array +} + +internal external interface LocalGetInfo : ExpressionInfo { + var index: Number +} + +internal external interface LocalSetInfo : ExpressionInfo { + var isTee: Boolean + var index: Number + var value: ExpressionRef +} + +internal external interface GlobalGetInfo : ExpressionInfo { + var name: String +} + +internal external interface GlobalSetInfo : ExpressionInfo { + var name: String + var value: ExpressionRef +} + +internal external interface LoadInfo : ExpressionInfo { + var isAtomic: Boolean + var isSigned: Boolean + var offset: Number + var bytes: Number + var align: Number + var ptr: ExpressionRef +} + +internal external interface StoreInfo : ExpressionInfo { + var isAtomic: Boolean + var offset: Number + var bytes: Number + var align: Number + var ptr: ExpressionRef + var value: ExpressionRef +} + +internal external interface `T$28` { + var low: Number + var high: Number +} + +internal external interface ConstInfo : ExpressionInfo { + var value: dynamic /* Number | `T$28` */ + get() = definedExternally + set(value) = definedExternally +} + +internal external interface UnaryInfo : ExpressionInfo { + var op: Operations + var value: ExpressionRef +} + +internal external interface BinaryInfo : ExpressionInfo { + var op: Operations + var left: ExpressionRef + var right: ExpressionRef +} + +internal external interface SelectInfo : ExpressionInfo { + var ifTrue: ExpressionRef + var ifFalse: ExpressionRef + var condition: ExpressionRef +} + +internal external interface DropInfo : ExpressionInfo { + var value: ExpressionRef +} + +internal external interface ReturnInfo : ExpressionInfo { + var value: ExpressionRef +} + +internal external interface NopInfo : ExpressionInfo + +internal external interface UnreachableInfo : ExpressionInfo + +internal external interface HostInfo : ExpressionInfo { + var op: Operations + var nameOperand: String? + var operands: Array +} + +internal external interface AtomicRMWInfo : ExpressionInfo { + var op: Operations + var bytes: Number + var offset: Number + var ptr: ExpressionRef + var value: ExpressionRef +} + +internal external interface AtomicCmpxchgInfo : ExpressionInfo { + var bytes: Number + var offset: Number + var ptr: ExpressionRef + var expected: ExpressionRef + var replacement: ExpressionRef +} + +internal external interface AtomicWaitInfo : ExpressionInfo { + var ptr: ExpressionRef + var expected: ExpressionRef + var timeout: ExpressionRef + var expectedType: Type +} + +internal external interface AtomicNotifyInfo : ExpressionInfo { + var ptr: ExpressionRef + var notifyCount: ExpressionRef +} + +internal external interface AtomicFenceInfo : ExpressionInfo { + var order: Number +} + +internal external interface SIMDExtractInfo : ExpressionInfo { + var op: Operations + var vec: ExpressionRef + var index: ExpressionRef +} + +internal external interface SIMDReplaceInfo : ExpressionInfo { + var op: Operations + var vec: ExpressionRef + var index: ExpressionRef + var value: ExpressionRef +} + +internal external interface SIMDShuffleInfo : ExpressionInfo { + var left: ExpressionRef + var right: ExpressionRef + var mask: Array +} + +internal external interface SIMDTernaryInfo : ExpressionInfo { + var op: Operations + var a: ExpressionRef + var b: ExpressionRef + var c: ExpressionRef +} + +internal external interface SIMDShiftInfo : ExpressionInfo { + var op: Operations + var vec: ExpressionRef + var shift: ExpressionRef +} + +internal external interface SIMDLoadInfo : ExpressionInfo { + var op: Operations + var offset: Number + var align: Number + var ptr: ExpressionRef +} + +internal external interface MemoryInitInfo : ExpressionInfo { + var segment: Number + var dest: ExpressionRef + var offset: ExpressionRef + var size: ExpressionRef +} + +internal external interface MemoryDropInfo : ExpressionInfo { + var segment: Number +} + +internal external interface MemoryCopyInfo : ExpressionInfo { + var dest: ExpressionRef + var source: ExpressionRef + var size: ExpressionRef +} + +internal external interface MemoryFillInfo : ExpressionInfo { + var dest: ExpressionRef + var value: ExpressionRef + var size: ExpressionRef +} + +internal external interface RefNullInfo : ExpressionInfo + +internal external interface RefIsNullInfo : ExpressionInfo { + var value: ExpressionRef +} + +internal external interface RefFuncInfo : ExpressionInfo { + var func: String +} + +internal external interface TryInfo : ExpressionInfo { + var body: ExpressionRef + var catchBody: ExpressionRef +} + +internal external interface ThrowInfo : ExpressionInfo { + var event: String + var operands: Array +} + +internal external interface RethrowInfo : ExpressionInfo { + var exnref: ExpressionRef +} + +internal external interface BrOnExnInfo : ExpressionInfo { + var name: String + var event: String + var exnref: ExpressionRef +} + +internal external interface PopInfo : ExpressionInfo + +internal external interface PushInfo : ExpressionInfo { + var value: ExpressionRef +} + +internal external fun getFunctionInfo(func: FunctionRef): FunctionInfo + +internal external interface FunctionInfo { + var name: String + var module: String? + var base: String? + var params: Type + var results: Type + var vars: Array + var body: ExpressionRef +} + +internal external fun getGlobalInfo(global: GlobalRef): GlobalInfo + +internal external interface GlobalInfo { + var name: String + var module: String? + var base: String? + var type: Type + var mutable: Boolean + var init: ExpressionRef +} + +internal external fun getExportInfo(export_: ExportRef): ExportInfo + +internal external interface ExportInfo { + var kind: ExternalKinds + var name: String + var value: String +} + +internal external fun getEventInfo(event: EventRef): EventInfo + +internal external interface EventInfo { + var name: String + var module: String? + var base: String? + var attribute: Number + var params: Type + var results: Type +} + +internal external fun getSideEffects(expr: ExpressionRef, features: Features): SideEffects + +internal external enum class SideEffects { + None, + Branches, + Calls, + ReadsLocal, + WritesLocal, + ReadsGlobal, + WritesGlobal, + ReadsMemory, + WritesMemory, + ImplicitTrap, + IsAtomic, + Throws, + Any +} + +internal external fun emitText(expression: ExpressionRef): String + +internal external fun emitText(expression: Module): String + +internal external fun readBinary(data: Uint8Array): Module + +internal external fun parseText(text: String): Module + +internal external fun getOptimizeLevel(): Number + +internal external fun setOptimizeLevel(level: Number): Number + +internal external fun getShrinkLevel(): Number + +internal external fun setShrinkLevel(level: Number): Number + +internal external fun getDebugInfo(): Boolean + +internal external fun setDebugInfo(on: Boolean) + +internal external fun getLowMemoryUnused(): Boolean + +internal external fun setLowMemoryUnused(on: Boolean) + +internal external fun getPassArgument(key: String): String? + +internal external fun setPassArgument(key: String, value: String?) + +internal external fun clearPassArguments() + +internal external fun getAlwaysInlineMaxSize(): Number + +internal external fun setAlwaysInlineMaxSize(size: Number) + +internal external fun getFlexibleInlineMaxSize(): Number + +internal external fun setFlexibleInlineMaxSize(size: Number) + +internal external fun getOneCallerInlineMaxSize(): Number + +internal external fun setOneCallerInlineMaxSize(size: Number) + +internal external fun exit(status: Number) + +internal open external class Relooper(module: Module) { + open fun addBlock(expression: ExpressionRef): RelooperBlockRef + open fun addBranch(from: RelooperBlockRef, to: RelooperBlockRef, condition: ExpressionRef, code: ExpressionRef) + open fun addBlockWithSwitch(code: ExpressionRef, condition: ExpressionRef): RelooperBlockRef + open fun addBranchForSwitch( + from: RelooperBlockRef, + to: RelooperBlockRef, + indexes: Array, + code: ExpressionRef + ) + + open fun renderAndDispose(entry: RelooperBlockRef, labelHelper: Number): ExpressionRef +} diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt new file mode 100644 index 000000000..f89db20e2 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt @@ -0,0 +1,11 @@ +@file:Suppress("PackageDirectoryMismatch", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation") + +package space.kscience.kmath.internal.binaryen + +internal typealias Type = Number +internal typealias ExpressionRef = Number +internal typealias FunctionRef = Number +internal typealias GlobalRef = Number +internal typealias ExportRef = Number +internal typealias EventRef = Number +internal typealias RelooperBlockRef = Number diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/emitter/emitter.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt similarity index 91% rename from kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/emitter/emitter.kt rename to kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt index 7707f53a2..1f7b09af8 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/emitter/emitter.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt @@ -3,7 +3,7 @@ * 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.estree.internal.emitter +package space.kscience.kmath.internal.emitter internal open external class Emitter { constructor(obj: Any) diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.extensions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt similarity index 97% rename from kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.extensions.kt rename to kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt index 9ba11e085..3aa31f921 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.extensions.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt @@ -3,7 +3,7 @@ * 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.estree.internal.estree +package space.kscience.kmath.internal.estree internal fun Program(sourceType: String, vararg body: dynamic) = object : Program { override var type = "Program" diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt similarity index 99% rename from kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.kt rename to kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt index a0e42db5d..e5254013e 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt @@ -3,7 +3,7 @@ * 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.estree.internal.estree +package space.kscience.kmath.internal.estree import kotlin.js.RegExp diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt new file mode 100644 index 000000000..ae6c7eb35 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt @@ -0,0 +1,7 @@ +package space.kscience.kmath.internal.stream + +import space.kscience.kmath.internal.emitter.Emitter + +internal open external class Stream : Emitter { + open fun pipe(dest: Any, options: Any): Any +} diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt similarity index 94% rename from kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt rename to kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt index a3c721ed4..9c012e3a3 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es2015.iterable.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt @@ -3,7 +3,7 @@ * 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.estree.internal.tsstdlib +package space.kscience.kmath.internal.tsstdlib internal external interface IteratorYieldResult { var done: Boolean? diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt similarity index 88% rename from kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt rename to kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt index d2413b3e3..0cd395f2c 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/tsstdlib/lib.es5.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt @@ -5,7 +5,7 @@ @file:Suppress("UNUSED_TYPEALIAS_PARAMETER", "DEPRECATION") -package space.kscience.kmath.estree.internal.tsstdlib +package space.kscience.kmath.internal.tsstdlib import kotlin.js.RegExp @@ -38,6 +38,8 @@ internal external interface RegExpConstructor { var lastMatch: String } +internal typealias Record = Any + internal external interface ConcatArray { var length: Number @@ -85,3 +87,10 @@ internal external interface ArrayLike { } internal typealias Extract = Any + +internal external interface PromiseLike { + fun then( + onfulfilled: ((value: T) -> Any?)? = definedExternally, + onrejected: ((reason: Any) -> Any?)? = definedExternally + ): PromiseLike +} diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt new file mode 100644 index 000000000..322a2fa7b --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt @@ -0,0 +1,231 @@ +@file:JsQualifier("WebAssembly") + +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", + "OVERRIDING_FINAL_MEMBER", + "RETURN_TYPE_MISMATCH_ON_OVERRIDE", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", + "ClassName", +) + +package space.kscience.kmath.internal.webassembly + +import space.kscience.kmath.internal.tsstdlib.PromiseLike +import org.khronos.webgl.ArrayBuffer +import org.khronos.webgl.ArrayBufferView +import org.khronos.webgl.Uint8Array +import org.w3c.fetch.Response +import kotlin.js.Promise + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +internal external interface CompileError { + companion object { + var prototype: CompileError + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +internal external interface Global { + var value: Any + fun valueOf(): Any + + companion object { + var prototype: Global + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +@JsName("Instance") +internal external interface Instance1 { + var exports: Exports + + companion object { + var prototype: Instance + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +internal external interface LinkError { + companion object { + var prototype: LinkError + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +internal external interface Memory { + var buffer: ArrayBuffer + fun grow(delta: Number): Number + + companion object { + var prototype: Memory + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +@JsName("Module") +internal external interface Module1 { + companion object { + var prototype: Module + fun customSections(moduleObject: Module, sectionName: String): Array + fun exports(moduleObject: Module): Array + fun imports(moduleObject: Module): Array + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +internal external interface RuntimeError { + companion object { + var prototype: RuntimeError + } +} + +@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") +internal external interface Table { + var length: Number + fun get(index: Number): Function<*>? + fun grow(delta: Number): Number + fun set(index: Number, value: Function<*>?) + + companion object { + var prototype: Table + } +} + +internal external interface GlobalDescriptor { + var mutable: Boolean? + get() = definedExternally + set(value) = definedExternally + var value: String /* "f32" | "f64" | "i32" | "i64" */ +} + +internal external interface MemoryDescriptor { + var initial: Number + var maximum: Number? + get() = definedExternally + set(value) = definedExternally +} + +internal external interface ModuleExportDescriptor { + var kind: String /* "function" | "global" | "memory" | "table" */ + var name: String +} + +internal external interface ModuleImportDescriptor { + var kind: String /* "function" | "global" | "memory" | "table" */ + var module: String + var name: String +} + +internal external interface TableDescriptor { + var element: String /* "anyfunc" */ + var initial: Number + var maximum: Number? + get() = definedExternally + set(value) = definedExternally +} + +internal external interface WebAssemblyInstantiatedSource { + var instance: Instance + var module: Module +} + +internal external fun compile(bytes: ArrayBufferView): Promise + +internal external fun compile(bytes: ArrayBuffer): Promise + +internal external fun compileStreaming(source: Response): Promise + +internal external fun compileStreaming(source: Promise): Promise + +internal external fun instantiate( + bytes: ArrayBufferView, + importObject: Imports = definedExternally, +): Promise + +internal external fun instantiate(bytes: ArrayBufferView): Promise + +internal external fun instantiate( + bytes: ArrayBuffer, + importObject: Imports = definedExternally, +): dynamic /* Promise | Promise */ + +internal external fun instantiate(bytes: ArrayBuffer): dynamic /* Promise | Promise */ + +internal external fun instantiate(moduleObject: Module, importObject: Imports = definedExternally): Promise + +internal external fun instantiate(moduleObject: Module): Promise + +internal external fun instantiateStreaming( + response: Response, + importObject: Imports = definedExternally, +): Promise + +internal external fun instantiateStreaming(response: Response): Promise + +internal external fun instantiateStreaming( + response: PromiseLike, + importObject: Imports = definedExternally, +): Promise + +internal external fun instantiateStreaming(response: PromiseLike): Promise + +internal external fun validate(bytes: ArrayBufferView): Boolean + +internal external fun validate(bytes: ArrayBuffer): Boolean + +internal external interface `T$0` { + var name: String + var kind: String +} + +internal external interface `T$1` { + var module: String + var name: String + var kind: String +} + +internal open external class Module { + constructor(bufferSource: ArrayBuffer) + constructor(bufferSource: Uint8Array) + + companion object { + fun customSections(module: Module, sectionName: String): Array + fun exports(module: Module): Array<`T$0`> + fun imports(module: Module): Array<`T$1`> + } +} + +@JsName("Instance") +internal open external class Instance(module: Module, importObject: Any = definedExternally) { + open var exports: Any +} + +@JsName("Memory") +internal open external class Memory1(memoryDescriptor: MemoryDescriptor) { + open var buffer: ArrayBuffer + open fun grow(numPages: Number): Number +} + +@JsName("Table") +internal open external class Table1(tableDescriptor: TableDescriptor) { + open var length: Number + open fun get(index: Number): Function<*> + open fun grow(numElements: Number): Number + open fun set(index: Number, value: Function<*>) +} + +internal external fun compile(bufferSource: Uint8Array): Promise + +internal external interface ResultObject { + var module: Module + var instance: Instance +} + +internal external fun instantiate( + bufferSource: Uint8Array, + importObject: Any = definedExternally, +): Promise + +internal external fun instantiate(bufferSource: Uint8Array): Promise + +internal external fun validate(bufferSource: Uint8Array): Boolean diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt new file mode 100644 index 000000000..095e46140 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt @@ -0,0 +1,22 @@ +@file:Suppress("INTERFACE_WITH_SUPERCLASS", + "OVERRIDING_FINAL_MEMBER", + "RETURN_TYPE_MISMATCH_ON_OVERRIDE", + "CONFLICTING_OVERLOADS", + "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", +) + +package space.kscience.kmath.internal.webassembly + +import space.kscience.kmath.internal.tsstdlib.Record + +internal typealias Exports = Record | Global | Memory | Table */> + +internal typealias ModuleImports = Record | Global | Memory | Table | Number */> + +internal typealias Imports = Record + +internal typealias CompileError1 = Error + +internal typealias LinkError1 = Error + +internal typealias RuntimeError1 = Error diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt new file mode 100644 index 000000000..a031a4de4 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -0,0 +1,155 @@ +package space.kscience.kmath.wasm.internal + +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.MST.* +import space.kscience.kmath.internal.binaryen.* +import space.kscience.kmath.internal.webassembly.Instance +import space.kscience.kmath.misc.StringSymbol +import space.kscience.kmath.operations.* +import space.kscience.kmath.internal.binaryen.Module as BinaryenModule +import space.kscience.kmath.internal.webassembly.Module as WasmModule + +private val spreader = eval("(obj, args) => obj(...args)") + +@Suppress("UnsafeCastFromDynamic") +internal sealed class WasmBuilder( + val binaryenType: Type, + val algebra: Algebra, + val target: MST, +) where T : Number { + val keys: MutableList = mutableListOf() + lateinit var ctx: BinaryenModule + + open fun visitSymbolic(mst: MST.Symbolic): ExpressionRef { + try { + algebra.bindSymbol(mst.value) + } catch (ignored: Throwable) { + null + }?.let { return visitNumeric(Numeric(it)) } + + var idx = keys.indexOf(mst.value) + + if (idx == -1) { + keys += mst.value + idx = keys.lastIndex + } + + return ctx.local.get(idx, binaryenType) + } + + abstract fun visitNumeric(mst: Numeric): ExpressionRef + + open fun visitUnary(mst: Unary): ExpressionRef = + error("Unary operation ${mst.operation} not defined in $this") + + open fun visitBinary(mst: Binary): ExpressionRef = + error("Binary operation ${mst.operation} not defined in $this") + + open fun createModule(): BinaryenModule = js("new \$module\$binaryen.Module()") + + fun visit(mst: MST): ExpressionRef = when (mst) { + is Symbolic -> visitSymbolic(mst) + is Numeric -> visitNumeric(mst) + + is Unary -> when { + algebra is NumericAlgebra && mst.value is Numeric -> visitNumeric( + Numeric(algebra.unaryOperationFunction(mst.operation)(algebra.number((mst.value as Numeric).value)))) + + else -> visitUnary(mst) + } + + is Binary -> when { + algebra is NumericAlgebra && mst.left is Numeric && mst.right is Numeric -> visitNumeric(Numeric( + algebra.binaryOperationFunction(mst.operation) + .invoke(algebra.number((mst.left as Numeric).value), algebra.number((mst.right as Numeric).value)) + )) + + else -> visitBinary(mst) + } + } + + val instance by lazy { + val c = WasmModule(with(createModule()) { + ctx = this + val expr = visit(target) + + addFunction( + "executable", + createType(Array(keys.size) { binaryenType }), + binaryenType, + arrayOf(), + expr + ) + + setOptimizeLevel(3) + optimizeFunction("executable") + addFunctionExport("executable", "executable") + val res = emitBinary() + dispose() + res + }) + + val i = Instance(c, js("{}") as Any) + val symbols = keys.map(::StringSymbol) + keys.clear() + + Expression { args -> + val params = symbols.map(args::getValue).toTypedArray() + spreader(i.exports.asDynamic().executable, params) as T + } + } +} + +internal class DoubleWasmBuilder(target: MST) : WasmBuilder(f64, DoubleField, target) { + override fun createModule(): BinaryenModule = readBinary(f64StandardFunctions) + + override fun visitNumeric(mst: Numeric): ExpressionRef = ctx.f64.const(mst.value) + + override fun visitUnary(mst: Unary): ExpressionRef = when (mst.operation) { + GroupOperations.MINUS_OPERATION -> ctx.f64.neg(visit(mst.value)) + GroupOperations.PLUS_OPERATION -> visit(mst.value) + PowerOperations.SQRT_OPERATION -> ctx.f64.sqrt(visit(mst.value)) + TrigonometricOperations.SIN_OPERATION -> ctx.call("sin", arrayOf(visit(mst.value)), f64) + TrigonometricOperations.COS_OPERATION -> ctx.call("cos", arrayOf(visit(mst.value)), f64) + TrigonometricOperations.TAN_OPERATION -> ctx.call("tan", arrayOf(visit(mst.value)), f64) + TrigonometricOperations.ASIN_OPERATION -> ctx.call("asin", arrayOf(visit(mst.value)), f64) + TrigonometricOperations.ACOS_OPERATION -> ctx.call("acos", arrayOf(visit(mst.value)), f64) + TrigonometricOperations.ATAN_OPERATION -> ctx.call("atan", arrayOf(visit(mst.value)), f64) + ExponentialOperations.SINH_OPERATION -> ctx.call("sinh", arrayOf(visit(mst.value)), f64) + ExponentialOperations.COSH_OPERATION -> ctx.call("cosh", arrayOf(visit(mst.value)), f64) + ExponentialOperations.TANH_OPERATION -> ctx.call("tanh", arrayOf(visit(mst.value)), f64) + ExponentialOperations.ASINH_OPERATION -> ctx.call("asinh", arrayOf(visit(mst.value)), f64) + ExponentialOperations.ACOSH_OPERATION -> ctx.call("acosh", arrayOf(visit(mst.value)), f64) + ExponentialOperations.ATANH_OPERATION -> ctx.call("atanh", arrayOf(visit(mst.value)), f64) + ExponentialOperations.EXP_OPERATION -> ctx.call("exp", arrayOf(visit(mst.value)), f64) + ExponentialOperations.LN_OPERATION -> ctx.call("log", arrayOf(visit(mst.value)), f64) + else -> super.visitUnary(mst) + } + + override fun visitBinary(mst: Binary): ExpressionRef = when (mst.operation) { + GroupOperations.PLUS_OPERATION -> ctx.f64.add(visit(mst.left), visit(mst.right)) + GroupOperations.MINUS_OPERATION -> ctx.f64.sub(visit(mst.left), visit(mst.right)) + RingOperations.TIMES_OPERATION -> ctx.f64.mul(visit(mst.left), visit(mst.right)) + FieldOperations.DIV_OPERATION -> ctx.f64.div(visit(mst.left), visit(mst.right)) + PowerOperations.POW_OPERATION -> ctx.call("pow", arrayOf(visit(mst.left), visit(mst.right)), f64) + else -> super.visitBinary(mst) + } +} + +internal class IntWasmBuilder(target: MST) : WasmBuilder(i32, IntRing, target) { + override fun visitNumeric(mst: Numeric): ExpressionRef = ctx.i32.const(mst.value) + + override fun visitUnary(mst: Unary): ExpressionRef = when (mst.operation) { + GroupOperations.MINUS_OPERATION -> ctx.i32.sub(ctx.i32.const(0), visit(mst.value)) + GroupOperations.PLUS_OPERATION -> visit(mst.value) + else -> super.visitUnary(mst) + } + + override fun visitBinary(mst: Binary): ExpressionRef = when (mst.operation) { + GroupOperations.PLUS_OPERATION -> ctx.i32.add(visit(mst.left), visit(mst.right)) + GroupOperations.MINUS_OPERATION -> ctx.i32.sub(visit(mst.left), visit(mst.right)) + RingOperations.TIMES_OPERATION -> ctx.i32.mul(visit(mst.left), visit(mst.right)) + else -> super.visitBinary(mst) + } +} diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt new file mode 100644 index 000000000..cb0d71ad5 --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt @@ -0,0 +1,8 @@ +package space.kscience.kmath.wasm.internal + +import space.kscience.kmath.internal.base64.toUint8Array + +internal val f64StandardFunctions by lazy { toUint8Array(B) } + +private const val B = + "AGFzbQEAAAABMghgAABgAXwBfGACfHwBfGAFf39/f38Bf2ACfH8Bf2ADfHx/AXxgAnx/AXxgA39/fwF/AxsaAAEBAQEBAQIDBAUBAQEBAQEBAgYBAQUBAQcEBQFwAQEBBQMBAAIGFQN/AUGgnwQLfwBBoJ8EC38AQaAfCwclAwZtZW1vcnkCAAtfX2hlYXBfYmFzZQMBCl9fZGF0YV9lbmQDAgrpaxoCAAvPBQMBfgF/AnwCQAJAAkAgAL0iAUIgiKdB/////wdxIgJBgIDA/wNJDQAgAkGAgMCAfGogAadyRQ0BRAAAAAAAAAAAIAAgAKGjDwsCQAJAIAJB/////gNLDQBEGC1EVPsh+T8hAyACQYGAgOMDSQ0BRAdcFDMmppE8IAAgAKIiAyADIAMgAyADIANECff9DeE9Aj+iRIiyAXXg70k/oKJEO49otSiCpL+gokRVRIgOVcHJP6CiRH1v6wMS1tS/oKJEVVVVVVVVxT+goiADIAMgAyADRIKSLrHFuLM/okRZAY0bbAbmv6CiRMiKWZzlKgBAoKJESy2KHCc6A8CgokQAAAAAAADwP6CjIACioSAAoUQYLURU+yH5P6APCyABQn9XDQJEAAAAAAAA8D8gAKFEAAAAAAAA4D+iIgAgAJ8iBL1CgICAgHCDvyIDIAOioSAEIAOgoyAEIAAgACAAIAAgACAARAn3/Q3hPQI/okSIsgF14O9JP6CiRDuPaLUogqS/oKJEVUSIDlXByT+gokR9b+sDEtbUv6CiRFVVVVVVVcU/oKIgACAAIAAgAESCki6xxbizP6JEWQGNG2wG5r+gokTIilmc5SoAQKCiREstihwnOgPAoKJEAAAAAAAA8D+go6KgIAOgIgAgAKAhAwsgAw8LRBgtRFT7IQlARAAAAAAAAAAAIAFCAFMbDwtEGC1EVPsh+T8gAEQAAAAAAADwP6BEAAAAAAAA4D+iIgCfIgMgAyAAIAAgACAAIAAgAEQJ9/0N4T0CP6JEiLIBdeDvST+gokQ7j2i1KIKkv6CiRFVEiA5Vwck/oKJEfW/rAxLW1L+gokRVVVVVVVXFP6CiIAAgACAAIABEgpIuscW4sz+iRFkBjRtsBua/oKJEyIpZnOUqAECgokRLLYocJzoDwKCiRAAAAAAAAPA/oKOiRAdcFDMmppG8oKChIgAgAKALdwEBfwJAIAC9QjSIp0H/D3EiAUH/B0sNACAARAAAAAAAAPC/oCIAIAAgAKIgACAAoKCfoBARDwsCQCABQZgISw0AIAAgAKBEAAAAAAAA8L8gACAAokQAAAAAAADwv6CfIACgo6AQEA8LIAAQEETvOfr+Qi7mP6AL0gQDAX4BfwN8AkACQAJAAkACQCAAvSIBQiCIp0H/////B3EiAkGAgMD/A0kNACACQYCAwIB8aiABp3JFDQFEAAAAAAAAAAAgACAAoaMPCwJAIAJB/////gNLDQAgAkGAgEBqQYCAgPIDTw0CIAAPC0QAAAAAAADwPyAAmaFEAAAAAAAA4D+iIgAgACAAIAAgACAARAn3/Q3hPQI/okSIsgF14O9JP6CiRDuPaLUogqS/oKJEVUSIDlXByT+gokR9b+sDEtbUv6CiRFVVVVVVVcU/oKIgACAAIAAgAESCki6xxbizP6JEWQGNG2wG5r+gokTIilmc5SoAQKCiREstihwnOgPAoKJEAAAAAAAA8D+goyEDIACfIQQgAkGz5rz/A0kNAkQYLURU+yH5PyAEIAQgA6KgIgAgAKBEB1wUMyamkbygoSEADAMLIABEGC1EVPsh+T+iRAAAAAAAAHA4oA8LIAAgAKIiBCAEIAQgBCAEIARECff9DeE9Aj+iRIiyAXXg70k/oKJEO49otSiCpL+gokRVRIgOVcHJP6CiRH1v6wMS1tS/oKJEVVVVVVVVxT+goiAEIAQgBCAERIKSLrHFuLM/okRZAY0bbAbmv6CiRMiKWZzlKgBAoKJESy2KHCc6A8CgokQAAAAAAADwP6CjIACiIACgDwtEGC1EVPsh6T8gBL1CgICAgHCDvyIFIAWgoSAEIASgIAOiRAdcFDMmppE8IAAgBSAFoqEgBCAFoKMiACAAoKGhoUQYLURU+yHpP6AhAAsgAJogACABQgBTGwvbAQQBfwF+AX8BfCMAQRBrIgEkACAAvSICQv///////////wCDvyEAAkACQCACQjSIp0H/D3EiA0GZCEkNACAAEBBE7zn6/kIu5j+gIQAMAQsCQCADQYAISQ0AIAAgAKBEAAAAAAAA8D8gACAAokQAAAAAAADwP6CfIACgo6AQECEADAELAkAgA0HlB0kNACAAIACiIgQgBEQAAAAAAADwP6CfRAAAAAAAAPA/oKMgAKAQESEADAELIAEgAEQAAAAAAABwR6A5AwgLIAFBEGokACAAmiAAIAJCAFMbC6gEBAF/AX4DfwJ8IwBBEGshASAAvSICQj+IpyEDAkACQAJAIAJCIIinQf////8HcSIEQYCAwKAESQ0AIAJC////////////AINCgICAgICAgPj/AFYNAUQYLURU+yH5v0QYLURU+yH5PyADGw8LAkACQCAEQf//7/4DSw0AQX8hBSAEQf////EDSw0BIARB//8/Sw0CIAEgALY4AgwgAA8LIACZIQACQAJAAkAgBEH//8v/A0sNACAEQf//l/8DSw0BIAAgAKBEAAAAAAAA8L+gIABEAAAAAAAAAECgoyEAQQAhBQwDCyAEQf//jYAESw0BIABEAAAAAAAA+L+gIABEAAAAAAAA+D+iRAAAAAAAAPA/oKMhAEECIQUMAgsgAEQAAAAAAADwv6AgAEQAAAAAAADwP6CjIQBBASEFDAELRAAAAAAAAPC/IACjIQBBAyEFCyAAIAAgAKIiBiAGoiIHIAcgByAHIAdEL2xqLES0or+iRJr93lIt3q2/oKJEbZp0r/Kws7+gokRxFiP+xnG8v6CiRMTrmJmZmcm/oKIgBiAHIAcgByAHIAdEEdoi4zqtkD+iROsNdiRLe6k/oKJEUT3QoGYNsT+gokRuIEzFzUW3P6CiRP+DAJIkScI/oKJEDVVVVVVV1T+goqCiIQcgBUF/TA0BIAVBA3QiBEGACGorAwAgByAEQaAIaisDAKEgAKGhIgCaIAAgAxshAAsgAA8LIAAgB6ELtgEEAX8BfgF/AXwjAEEQayIBJAAgAL0iAkL///////////8Ag78hAAJAAkACQCACQjSIp0H/D3EiA0H9B0sNACADQd4HSw0BIAMNAiABIAC2OAIMDAILIABEAAAAAAAA8D8gAKGjIgAgAKAQEUQAAAAAAADgP6IhAAwBCyAAIACgIgQgBCAAokQAAAAAAADwPyAAoaOgEBFEAAAAAAAA4D+iIQALIAFBEGokACAAmiAAIAJCAFMbC5IBAQN8RAAAAAAAAPA/IAAgAKIiAkQAAAAAAADgP6IiA6EiBEQAAAAAAADwPyAEoSADoSACIAIgAiACRJAVyxmgAfo+okR3UcEWbMFWv6CiRExVVVVVVaU/oKIgAiACoiIDIAOiIAIgAkTUOIi+6fqovaJExLG0vZ7uIT6gokStUpyAT36SvqCioKIgACABoqGgoAuEFgYHfwF8Cn8BfAN/AnwjAEGwBGsiBSQAIAIgAkF9akEYbSIGQQAgBkEAShsiB0FobGohCAJAIARBAnRBwAhqKAIAIgkgA0F/aiICakEASA0AIAkgA2ohCiAHIAJrIQIgB0EBaiADa0ECdEHQCGohCyAFQcACaiEGA0ACQAJAIAJBAEgNACALKAIAtyEMDAELRAAAAAAAAAAAIQwLIAYgDDkDACAGQQhqIQYgC0EEaiELIAJBAWohAiAKQX9qIgoNAAsLIAhBaGohDQJAAkAgA0EBSA0AIAVBwAJqIANBA3RqQXhqIQ5BACEKA0BEAAAAAAAAAAAhDCAAIQIgAyELIA4hBgNAIAwgAisDACAGKwMAoqAhDCACQQhqIQIgBkF4aiEGIAtBf2oiCw0ACyAFIApBA3RqIAw5AwAgDkEIaiEOIAogCUghAiAKQQFqIQogAg0ADAILCyAFQQAgCUEAIAlBAEobQQN0QQhqEBkaC0EXIA1rIQ9BGCANayEQIAVB4ANqIAlBAnRqQXxqIREgBUHgA2pBfGohEiAFQXhqIRMgBUEIciEUIAkhBgN/IAUgBkEDdCIVaisDACEMAkAgBkEBSCIWDQAgEyAVaiECIAVB4ANqIQsgBiEKA0ACQAJAIAxEAAAAAAAAcD6iIheZRAAAAAAAAOBBYw0AQYCAgIB4IQ4MAQsgF6ohDgsCQAJAIAwgDrciF0QAAAAAAABwwaKgIgyZRAAAAAAAAOBBYw0AQYCAgIB4IQ4MAQsgDKohDgsgCyAONgIAIAtBBGohCyACKwMAIBegIQwgAkF4aiECIApBf2oiCg0ACwsCQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAMIA0QEyIMIAxEAAAAAAAAwD+inEQAAAAAAAAgwKKgIgyZRAAAAAAAAOBBYw0AQYCAgIB4IRggDEGAgICAeLehIQwgDUEBSCIZRQ0BDAILIAwgDKoiGLehIQwgDUEBSCIZDQELIAVB4ANqIAZBAnRqQXxqIgIgAigCACICIAIgEHUiAiAQdGsiCzYCACACIBhqIRggCyAPdSIaQQFIDQIMAQsCQCANRQ0AQQIhGiAMRAAAAAAAAOA/ZkEBc0UNAUEAIRogDEQAAAAAAAAAAGENAwwECyAFQeADaiAGQQJ0akF8aigCAEEXdSIaQQFIDQELAkACQCAWDQBBACEWIAVB4ANqIQIgBiEOA0AgAigCACELQf///wchCgJAAkAgFg0AIAtFDQFBASEWQYCAgAghCgsgAiAKIAtrNgIAIAJBBGohAiAOQX9qIg4NAQwDC0EAIRYgAkEEaiECIA5Bf2oiDg0ADAILC0EAIRYLAkACQAJAIBkNACANQQJGDQEgDUEBRw0AIAVB4ANqIAZBAnRqQXxqIgIgAigCAEH///8DcTYCAAsgGEEBaiEYIBpBAkcNAgwBCyAFQeADaiAGQQJ0akF8aiICIAIoAgBB////AXE2AgAgGEEBaiEYIBpBAkcNAQtEAAAAAAAA8D8gDKEhDEECIRogFkUNACAMRAAAAAAAAPA/IA0QE6EiDEQAAAAAAAAAAGENAQwCCyAMRAAAAAAAAAAAYg0BCwJAIAYgCUwNACASIAZBAnRqIQJBACELIAYhCgNAIAIoAgAgC3IhCyACQXxqIQIgCkF/aiIKIAlKDQALIAsNAgsgESECIAYhDgNAIA5BAWohDiACKAIAIQsgAkF8aiECIAtFDQALIAZBAWohAgJAIANBAUgNACAFQcACaiADIAZqQQN0aiEWA0AgBUHAAmogBiADakEDdGogAiIKIAdqQQJ0QdAIaigCALc5AwBEAAAAAAAAAAAhDCAAIQIgFiEGIAMhCwNAIAwgAisDACAGKwMAoqAhDCACQQhqIQIgBkF4aiEGIAtBf2oiCw0ACyAFIApBA3RqIAw5AwAgFkEIaiEWIApBAWohAiAKIQYgCiAOSA0ADAsLCyAUIBVqQQAgDiACIA4gAkobIAZrQQN0EBkaIAcgBmpBAnRB1AhqIQIgBUHAAmogAyAGakEDdGohCwNAIAsgAigCALc5AwAgAkEEaiECIAtBCGohCyAGQQFqIgYgDkgNAAsgDiEGDAoLAkAgDEEAIA1rEBMiDEQAAAAAAABwQWZBAXNFDQAgDJlEAAAAAAAA4EFjDQJBgICAgHghAgwDCyAGQQJ0IQsgDEQAAAAAAABwPqIiF5lEAAAAAAAA4EFjDQNBgICAgHghAgwECyAFQeADaiAGQQJ0akF8aiECIA0hCANAIAZBf2ohBiAIQWhqIQggAigCACELIAJBfGohAiALRQ0AC0EAIQ4gBkEATg0FDAYLIAyqIQILIA0hCAwCCyAXqiECCyAFQeADaiALaiELAkACQCAMIAK3RAAAAAAAAHDBoqAiDJlEAAAAAAAA4EFjDQBBgICAgHghCgwBCyAMqiEKCyALIAo2AgAgBkEBaiEGCyAFQeADaiAGQQJ0aiACNgIAQQAhDiAGQQBIDQELIAZBAWohCkQAAAAAAADwPyAIEBMhDCAFQeADaiAGQQJ0aiECIAUgBkEDdGohCwNAIAsgDCACKAIAt6I5AwAgAkF8aiECIAtBeGohCyAMRAAAAAAAAHA+oiEMIApBf2oiCiAOSg0ACyAGQQBIDQAgBSAGQQN0aiEOIAYhAgNAIAYgAiIDayEWRAAAAAAAAAAAIQxBACECQQAhCwJAA0AgDCACQaAeaisDACAOIAJqKwMAoqAhDCALIAlODQEgAkEIaiECIAsgFkkhCiALQQFqIQsgCg0ACwsgBUGgAWogFkEDdGogDDkDACAOQXhqIQ4gA0F/aiECIANBAEoNAAsLAkACQAJAAkACQAJAAkACQCAEQX9qQQJJDQAgBEUNASAEQQNHDQdEAAAAAAAAAAAhGwJAIAZBAUgNACAFQaABaiAGQQN0aiILQXhqIQIgCysDACEMIAYhCwNAIAIgAisDACIcIAygIhc5AwAgAkEIaiAMIBwgF6GgOQMAIAJBeGohAiAXIQwgC0F/aiILQQBKDQALIAZBAkgNACAFQaABaiAGQQN0aiILQXhqIQIgCysDACEMIAYhCwNAIAIgAisDACIcIAygIhc5AwAgAkEIaiAMIBwgF6GgOQMAIAJBeGohAiAXIQwgC0F/aiILQQFKDQALIAZBAkgNACAFQaABaiAGQQN0aiECRAAAAAAAAAAAIRsDQCAbIAIrAwCgIRsgAkF4aiECIAZBf2oiBkEBSg0ACwsgBSsDoAEhDCAaRQ0EIAEgDJo5AwAgASAFKwOoAZo5AwggASAbmjkDEAwHCyAGQQBIDQEgBkEBaiELIAVBoAFqIAZBA3RqIQJEAAAAAAAAAAAhDANAIAwgAisDAKAhDCACQXhqIQIgC0F/aiILQQBKDQAMAwsLIAZBAEgNAyAGQQFqIQsgBUGgAWogBkEDdGohAkQAAAAAAAAAACEMA0AgDCACKwMAoCEMIAJBeGohAiALQX9qIgtBAEoNAAwFCwtEAAAAAAAAAAAhDAsgASAMmiAMIBobOQMAIAUrA6ABIAyhIQwCQCAGQQFIDQAgBUGgAWpBCHIhAgNAIAwgAisDAKAhDCACQQhqIQIgBkF/aiIGDQALCyABIAyaIAwgGhs5AwgMAwsgASAMOQMAIAEgBSkDqAE3AwggASAbOQMQDAILRAAAAAAAAAAAIQwLIAEgDJogDCAaGzkDAAsgBUGwBGokACAYQQdxDwsgDiEGDAALC8MKBgF/AX4DfwN8AX8BfCMAQTBrIgIkACAAvSIDQj+IpyEEAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCADQiCIpyIFQf////8HcSIGQfrUvYAESw0AIAVB//8/cUH7wyRGDQMgBkH8souABEsNASAERQ0GIAEgAEQAAEBU+yH5P6AiAEQxY2IaYbTQPaAiBzkDACABIAAgB6FEMWNiGmG00D2gOQMIIAJBMGokAEF/DwsCQCAGQbuM8YAESw0AIAZBvPvXgARLDQIgBkH8ssuABEYNAyAERQ0KIAEgAEQAADB/fNkSQKAiAETKlJOnkQ7pPaAiBzkDACABIAAgB6FEypSTp5EO6T2gOQMIIAJBMGokAEF9DwsgBkH6w+SJBE0NAiAGQYCAwP8HSQ0DIAEgACAAoSIAOQMAIAEgADkDCCACQTBqJABBAA8LIARFDQUgASAARAAAQFT7IQlAoCIARDFjYhphtOA9oCIHOQMAIAEgACAHoUQxY2IaYbTgPaA5AwggAkEwaiQAQX4PCyAGQfvD5IAERw0CCyABIAAgAESDyMltMF/kP6JEAAAAAAAAOEOgRAAAAAAAADjDoCIHRAAAQFT7Ifm/oqAiCCAHRDFjYhphtNA9oiIJoSIAOQMAIAZBFHYiCiAAvUI0iKdB/w9xa0ERSCEFAkACQAJAIAeZRAAAAAAAAOBBYw0AQYCAgIB4IQYgBUUNAQwCCyAHqiEGIAUNAQsgASAIIAdEAABgGmG00D2iIgChIgsgB0RzcAMuihmjO6IgCCALoSAAoaEiCaEiADkDAAJAIAogAL1CNIinQf8PcWtBMkgNACABIAsgB0QAAAAuihmjO6IiAKEiCCAHRMFJICWag3s5oiALIAihIAChoSIJoSIAOQMADAELIAshCAsgASAIIAChIAmhOQMIIAJBMGokACAGDwsgA0L/////////B4NCgICAgICAgLDBAIS/IgCZRAAAAAAAAOBBYw0DQYCAgIB4IQUMBAsgBEUNBSABIABEAABAVPshGUCgIgBEMWNiGmG08D2gIgc5AwAgASAAIAehRDFjYhphtPA9oDkDCCACQTBqJABBfA8LIAEgAEQAAEBU+yH5v6AiAEQxY2IaYbTQvaAiBzkDACABIAAgB6FEMWNiGmG00L2gOQMIIAJBMGokAEEBDwsgASAARAAAQFT7IQnAoCIARDFjYhphtOC9oCIHOQMAIAEgACAHoUQxY2IaYbTgvaA5AwggAkEwaiQAQQIPCyAAqiEFCyACIAW3Igc5AxACQAJAIAAgB6FEAAAAAAAAcEGiIgCZRAAAAAAAAOBBYw0AQYCAgIB4IQUMAQsgAKohBQsgAiAFtyIHOQMYIAIgACAHoUQAAAAAAABwQaIiADkDICAARAAAAAAAAAAAYg0CIAJBEGpBCHIhBUECIQoDQCAKQX9qIQogBSsDACEAIAVBeGohBSAARAAAAAAAAAAAYQ0ADAQLCyABIABEAAAwf3zZEsCgIgBEypSTp5EO6b2gIgc5AwAgASAAIAehRMqUk6eRDum9oDkDCCACQTBqJABBAw8LIAEgAEQAAEBU+yEZwKAiAEQxY2IaYbTwvaAiBzkDACABIAAgB6FEMWNiGmG08L2gOQMIIAJBMGokAEEEDwtBAiEKCyACQRBqIAIgBkEUdkHqd2ogCkEBakEBEAghBSACKwMAIQACQCAERQ0AIAEgAJo5AwAgASACKwMImjkDCCACQTBqJABBACAFaw8LIAEgADkDACABIAIpAwg3AwggAkEwaiQAIAULmwEBA3wgACAAoiIDIAMgA6KiIANEfNXPWjrZ5T2iROucK4rm5Vq+oKIgAyADRH3+sVfjHcc+okTVYcEZoAEqv6CiRKb4EBEREYE/oKAhBCADIACiIQUCQCACRQ0AIAAgBURJVVVVVVXFP6IgAyABRAAAAAAAAOA/oiAFIASioaIgAaGgoQ8LIAUgAyAEokRJVVVVVVXFv6CiIACgC5ICAgJ/AXwjAEEQayIBJAACQAJAAkAgAL1CIIinQf////8HcSICQfvDpP8DSw0AIAJBncGa8gNLDQEgASAARAAAAAAAAHBHoDkDACABQRBqJABEAAAAAAAA8D8PCyACQYCAwP8HSQ0BIAFBEGokACAAIAChDwsgAEQAAAAAAAAAABAHIQAgAUEQaiQAIAAPCyAAIAEQCSECIAErAwghACABKwMAIQMCQAJAAkAgAkEDcSICQQJGDQAgAkEBRg0BIAINAiADIAAQByEAIAFBEGokACAADwsgAyAAEAchACABQRBqJAAgAJoPCyADIABBARAKIQAgAUEQaiQAIACaDwsgAyAAQQEQCiEAIAFBEGokACAACyQAIABEi90aFWYglsCgEA5EAAAAAAAAwH+iRAAAAAAAAMB/ogvaAQMBfwF+AX8jAEEQayIBJAAgAL1C////////////AIMiAr8hAAJAAkACQCACQiCIpyIDQcHcmP8DSw0AIANB//+/8gNLDQEgASAARAAAAAAAAHBHoDkDCCABQRBqJABEAAAAAAAA8D8PCyADQcHcmIQESw0BIAAQDiEAIAFBEGokACAARAAAAAAAAPA/IACjoEQAAAAAAADgP6IPCyABQRBqJAAgABAPIgAgAKIgAEQAAAAAAADwP6AiACAAoKNEAAAAAAAA8D+gDwsgABAMIQAgAUEQaiQAIAALoAQEAX8BfgJ/A3wjAEEQayIBJAAgAL0iAkI/iKchAwJAAkACQAJAAkACQAJAAkACQAJAIAJCIIinQf////8HcSIEQavGmIQESQ0AIAJC////////////AINCgICAgICAgPj/AFgNASABQRBqJAAgAA8LIARBw9zY/gNJDQEgBEGyxcL/A08NAyADQQFzIANrIQQMBgsgAETvOfr+Qi6GQGRBAXMNASABQRBqJAAgAEQAAAAAAADgf6IPCyAEQYCAwPEDTQ0CQQAhBEQAAAAAAAAAACEFIAAhBgwFCyAARNK8et0rI4bAY0EBcw0AIAFEAAAAAAAAoLYgAKO2OAIMRAAAAAAAAAAAIQcgAERRMC3VEEmHwGMNBQsgAET+gitlRxX3P6IgA0EDdEHgHmorAwCgIgeZRAAAAAAAAOBBYw0BQYCAgIB4IQQMAgsgASAARAAAAAAAAOB/oDkDACABQRBqJAAgAEQAAAAAAADwP6APCyAHqiEECyAAIAS3IgdEAADg/kIu5r+ioCIAIAdEdjx5Ne856j2iIgWhIQYLIAAgBiAGIAYgBqIiByAHIAcgByAHRNCkvnJpN2Y+okTxa9LFQb27vqCiRCzeJa9qVhE/oKJEk72+FmzBZr+gokQ+VVVVVVXFP6CioSIHokQAAAAAAAAAQCAHoaMgBaGgRAAAAAAAAPA/oCEHIARFDQAgByAEEBMhBwsgAUEQaiQAIAcL2QYEAX8BfgJ/BHwjAEEQayEBIAC9IgJCP4inIQMCQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCACQiCIp0H/////B3EiBEH60I2CBEkNACACQv///////////wCDQoCAgICAgID4/wBYDQEgAA8LIARBw9zY/gNJDQEgBEGxxcL/A0sNAiADRQ0GIABEAADg/kIu5j+gIQVBfyEERHY8eTXvOeq9IQYMCgsgA0UNA0QAAAAAAADwvw8LIARB//+/5ANLDQEgBEH//z9LDQMgASAAtjgCDCAADwsgAET+gitlRxX3P6IhBkQAAAAAAADgvyEFIAMNBgwFC0EAIQQMBwsgAETvOfr+Qi6GQGRFDQIgAEQAAAAAAADgf6IPCyAADwsgAEQAAOD+Qi7mv6AhBUEBIQREdjx5Ne856j0hBgwDCyAARP6CK2VHFfc/oiEGC0QAAAAAAADgPyEFCwJAAkAgBiAFoCIFmUQAAAAAAADgQWMNAEGAgICAeCEEDAELIAWqIQQLIAS3IgVEdjx5Ne856j2iIQYgACAFRAAA4P5CLua/oqAhBQsgBSAFIAahIgChIAahIQYLIAAgAEQAAAAAAADgP6IiB6IiBSAFIAUgBSAFIAVELcMJbrf9ir6iRDlS5obKz9A+oKJEt9uqnhnOFL+gokSFVf4ZoAFaP6CiRPQQEREREaG/oKJEAAAAAAAA8D+gIghEAAAAAAAACEAgByAIoqEiB6FEAAAAAAAAGEAgACAHoqGjoiEHAkACQAJAAkACQCAERQ0AIAAgByAGoaIgBqEgBaEhBSAEQQFGDQEgBEF/Rw0CIAAgBaFEAAAAAAAA4D+iRAAAAAAAAOC/oA8LIAAgACAHoiAFoaEPCyAARAAAAAAAANC/Y0EBcw0BIAUgAEQAAAAAAADgP6ChRAAAAAAAAADAog8LIARB/wdqrUI0hr8hBiAEQTlJDQEgACAFoUQAAAAAAADwP6AiACAAoEQAAAAAAADgf6IgACAGoiAEQYAIRhtEAAAAAAAA8L+gDwsgACAFoSIAIACgRAAAAAAAAPA/oA8LRAAAAAAAAPA/Qf8HIARrrUI0hr8iB6EgACAFIAegoSAEQRRIIgQbIAAgBaFEAAAAAAAA8D8gBBugIAaiC6IDAwF+A38CfAJAAkACQAJAAkAgAL0iAUIAUw0AIAFCIIinIgJB//8/TQ0AIAJB//+//wdLDQNBgIDA/wMhA0GBeCEEIAJBgIDA/wNHDQEgAacNAkQAAAAAAAAAAA8LAkAgAUL///////////8Ag0IAUQ0AIAFCf1cNBCAARAAAAAAAAFBDor0iAUIgiKchA0HLdyEEDAILRAAAAAAAAPC/IAAgAKKjDwsgAiEDCyAEIANB4r4laiICQRR2arciBUQAAOD+Qi7mP6IgAkH//z9xQZ7Bmv8Daq1CIIYgAUL/////D4OEv0QAAAAAAADwv6AiACAFRHY8eTXvOeo9oiAAIABEAAAAAAAAAECgoyIFIAAgAEQAAAAAAADgP6KiIgYgBSAFoiIFIAWiIgAgACAARJ/GeNAJmsM/okSveI4dxXHMP6CiRAT6l5mZmdk/oKIgBSAAIAAgAEREUj7fEvHCP6JE3gPLlmRGxz+gokRZkyKUJEnSP6CiRJNVVVVVVeU/oKKgoKKgIAahoKAhAAsgAA8LIAAgAKFEAAAAAAAAAACjC4kEBAF/AX4BfwN8IwBBEGshASAAvSICQiCIpyEDAkACQAJAAkACQCACQgBTDQAgA0H5hOr+A00NACADQf//v/8HTQ0BIAAPCwJAIANBgIDA/3tJDQAgAEQAAAAAAADwv2INA0QAAAAAAADw/w8LAkAgA0EBdEH////JB0sNACADQYCAwP8HcUUNBCAADwtEAAAAAAAAAAAhBCADQcX9yv57Tw0ARAAAAAAAAAAAIQUMAQtEAAAAAAAAAAAhBAJAIABEAAAAAAAA8D+gIgW9IgJCIIinQeK+JWoiAUEUdkGBeGoiA0E1Sg0AIAAgBaFEAAAAAAAA8D+gIAAgBUQAAAAAAADwv6ChIANBAUobIAWjIQQLIAFB//8/cUGewZr/A2qtQiCGIAJC/////w+DhL9EAAAAAAAA8L+gIQAgA7chBQsgBUQAAOD+Qi7mP6IgACAEIAVEdjx5Ne856j2ioCAAIABEAAAAAAAAAECgoyIFIAAgAEQAAAAAAADgP6KiIgYgBSAFoiIEIASiIgUgBSAFRJ/GeNAJmsM/okSveI4dxXHMP6CiRAT6l5mZmdk/oKIgBCAFIAUgBUREUj7fEvHCP6JE3gPLlmRGxz+gokRZkyKUJEnSP6CiRJNVVVVVVeU/oKKgoKKgIAahoKAPCyAAIAChRAAAAAAAAAAAow8LIAEgALY4AgwgAAvHEAYBfAF+A38BfgV/CHxEAAAAAAAA8D8hAgJAIAG9IgNCIIinIgRB/////wdxIgUgA6ciBnJFDQAgAL0iB0IgiKchCAJAIAenIgkNACAIQYCAwP8DRg0BCwJAAkAgCEH/////B3EiCkGAgMD/B0sNACAJQQBHIApBgIDA/wdGcQ0AIAVBgIDA/wdLDQAgBkUNASAFQYCAwP8HRw0BCyAAIAGgDwtBACELAkACQAJAAkAgCEF/Sg0AQQIhCyAFQf///5kESw0AQQAhCyAFQYCAwP8DSQ0AIAVBFHYhDCAFQYCAgIoESQ0BQQIgBkGzCCAMayILdiIMQQFxa0EAIAwgC3QgBkYbIQsLIAZFDQEMAgtBACELIAYNAUECIAVBkwggDGsiBnYiC0EBcWtBACALIAZ0IAVGGyELCwJAAkACQAJAIAVBgIDA/wdHDQAgCkGAgMCAfGogCXJFDQUgCkGAgMD/A0kNASABRAAAAAAAAAAAIARBf0obDwsCQCAFQYCAwP8DRw0AIARBf0wNAyAADwsgBEGAgICABEcNASAAIACiDwtEAAAAAAAAAAAgAZogBEF/ShsPCyAIQQBIDQEgBEGAgID/A0cNASAAnw8LRAAAAAAAAPA/IACjDwsgAJkhAgJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAkNACAKRQ0BIApBgICAgARyQYCAwP8HRg0BC0QAAAAAAADwPyENIAhBf0oNAyALQQFGDQEgCw0DIAAgAKEiASABow8LRAAAAAAAAPA/IAKjIAIgBEEASBshAiAIQX9KDQsgCyAKQYCAwIB8anJFDQEgApogAiALQQFGGw8LRAAAAAAAAPC/IQ0gBUGBgICPBE8NAgwDCyACIAKhIgEgAaMPCyAFQYGAgI8ESQ0BCwJAIAVBgYDAnwRJDQAgCkH//7//A0sNAkQAAAAAAADwf0QAAAAAAAAAACAEQQBIGw8LIApB/v+//wNLDQIgDUScdQCIPOQ3fqJEnHUAiDzkN36iIA1EWfP4wh9upQGiRFnz+MIfbqUBoiAEQQBIGw8LQQAhBQJAAkAgCkH//z9LDQAgAkQAAAAAAABAQ6IiAr1CIIinIQpBSyEEDAELQQAhBAsgCkH//z9xIgZBgIDA/wNyIQggCkEUdSAEakGBeGohBCAGQY+xDkkNAyAGQfrsLk8NAkEBIQUMAwtEAAAAAAAA8H9EAAAAAAAAAAAgBEEAShsPCyAKQYGAwP8DSQ0CIA1EnHUAiDzkN36iRJx1AIg85Dd+oiANRFnz+MIfbqUBokRZ8/jCH26lAaIgBEEAShsPCyAIQYCAQGohCCAEQQFqIQQLIAVBA3QiBkGQH2orAwAiDiAIrUIghiACvUL/////D4OEvyIPIAZB8B5qKwMAIhChIhFEAAAAAAAA8D8gECAPoKMiEqIiAr1CgICAgHCDvyIAIAAgAKIiE0QAAAAAAAAIQKAgAiAAoCASIBEgACAIQQF1QYCAgIACciAFQRJ0akGAgCBqrUIghr8iFKKhIAAgDyAUIBChoaKhoiIPoiACIAKiIgAgAKIgACAAIAAgACAARO9ORUoofso/okRl28mTSobNP6CiRAFBHalgdNE/oKJETSaPUVVV1T+gokT/q2/btm3bP6CiRAMzMzMzM+M/oKKgIhCgvUKAgICAcIO/IgCiIhEgDyAAoiACIBAgAEQAAAAAAAAIwKAgE6GhoqAiAqC9QoCAgIBwg78iAEQAAADgCcfuP6IiDyAGQYAfaisDACACIAAgEaGhRP0DOtwJx+4/oiAARPUBWxTgLz6+oqCgIhCgoCAEtyICoL1CgICAgHCDvyIAIAKhIA6hIA+hIQ4MAQsgAkQAAAAAAADwv6AiAEQAAABgRxX3P6IiAiAARETfXfgLrlQ+oiAAIACiRAAAAAAAAOA/IAAgAEQAAAAAAADQv6JEVVVVVVVV1T+goqGiRP6CK2VHFfe/oqAiEKC9QoCAgIBwg78iACACoSEOCyAAIANCgICAgHCDvyIPoiICIBAgDqEgAaIgASAPoSAAoqAiAaAiAL0iA6chBQJAAkACQAJAAkAgA0IgiKciCEGAgMCEBEgNACAIQYCAwPt7aiAFckUNASANRJx1AIg85Dd+okScdQCIPOQ3fqIPCyAIQYD4//8HcUGAmMOEBEkNAiAIQYDovPsDaiAFckUNASANRFnz+MIfbqUBokRZ8/jCH26lAaIPCyABRP6CK2VHFZc8oCAAIAKhZEEBcw0BIA1EnHUAiDzkN36iRJx1AIg85Dd+og8LIAEgACACoWVBAXNFDQELQQAhBQJAIAhB/////wdxIgZBgYCA/wNJDQBBAEGAgMAAIAZBFHZBgnhqdiAIaiIGQf//P3FBgIDAAHJBkwggBkEUdkH/D3EiBGt2IgVrIAUgCEEASBshBSABIAJBgIBAIARBgXhqdSAGca1CIIa/oSICoL0hAwsCQCAFQRR0IANCgICAgHCDvyIARAAAAABDLuY/oiIPIAEgACACoaFE7zn6/kIu5j+iIABEOWyoDGFcIL6ioCICoCIBIAEgASABIAGiIgAgACAAIAAgAETQpL5yaTdmPqJE8WvSxUG9u76gokQs3iWvalYRP6CiRJO9vhZswWa/oKJEPlVVVVVVxT+goqEiAKIgAEQAAAAAAAAAwKCjIAIgASAPoaEiACABIACioKGhRAAAAAAAAPA/oCIBvSIDQiCIp2oiCEH//z9KDQAgDSABIAUQE6IPCyANIAitQiCGIANC/////w+DhL+iDwsgDURZ8/jCH26lAaJEWfP4wh9upQGiDwsgAgu4AQEBfwJAAkACQAJAIAFBgAhIDQAgAEQAAAAAAADgf6IhACABQYF4aiICQYAISA0BIAFBgnBqIgFB/wcgAUH/B0gbIQEgAEQAAAAAAADgf6IhAAwDCyABQYF4Sg0CIABEAAAAAAAAYAOiIQAgAUHJB2oiAkGBeEoNASABQZIPaiIBQYJ4IAFBgnhKGyEBIABEAAAAAAAAYAOiIQAMAgsgAiEBDAELIAIhAQsgACABQf8Haq1CNIa/oguiAgICfwF8IwBBEGsiASQAAkACQAJAIAC9QiCIp0H/////B3EiAkH7w6T/A0sNACACQf//v/IDSw0BIAEgAEQAAAAAAABwOKIgAEQAAAAAAABwR6AgAkGAgMAASRs5AwAgAUEQaiQAIAAPCyACQYCAwP8HSQ0BIAFBEGokACAAIAChDwsgAEQAAAAAAAAAAEEAEAohACABQRBqJAAgAA8LIAAgARAJIQIgASsDCCEAIAErAwAhAwJAAkACQCACQQNxIgJBAkYNACACQQFGDQEgAg0CIAMgAEEBEAohACABQRBqJAAgAA8LIAMgAEEBEAohACABQRBqJAAgAJoPCyADIAAQByEAIAFBEGokACAADwsgAyAAEAchACABQRBqJAAgAJoLrgEDAX4CfAF/RAAAAAAAAOC/RAAAAAAAAOA/IAC9IgFCAFMbIQIgAUL///////////8AgyIBvyEDAkACQAJAIAFCIIinIgRBwdyYhARLDQAgAxAPIQMgBEH//7//A0sNAiAEQYCAwPIDSQ0BIAIgAyADoCADIAOiIANEAAAAAAAA8D+go6GiDwsgAiACoCADEAyiIQALIAAPCyACIAMgAyADRAAAAAAAAPA/oKOgoguwAwMBfgJ/A3wCQAJAIAC9IgNCgICAgID/////AINCgYCAgPCE5fI/VCIEDQBEGC1EVPsh6T8gAJogACADQj+IpyIFG6FEB1wUMyamgTwgAZogASAFG6GgIQBEAAAAAAAAAAAhAQwBCwsgACAAIAAgAKIiBqIiB0RjVVVVVVXVP6IgASAGIAEgByAGIAaiIgggCCAIIAggCERzU2Dby3XzvqJEppI3oIh+FD+gokQBZfLy2ERDP6CiRCgDVskibW0/oKJEN9YGhPRklj+gokR6/hARERHBP6AgBiAIIAggCCAIIAhE1Hq/dHAq+z6iROmn8DIPuBI/oKJEaBCNGvcmMD+gokQVg+D+yNtXP6CiRJOEbunjJoI/oKJE/kGzG7qhqz+goqCioKKgoCIGoCEIAkAgBA0AQQEgAkEBdGu3IgEgACAGIAggCKIgCCABoKOhoCIIIAigoSIImiAIIAUbDwsCQCACRQ0ARAAAAAAAAPC/IAijIgEgCL1CgICAgHCDvyIHIAG9QoCAgIBwg78iCKJEAAAAAAAA8D+gIAYgByAAoaEgCKKgoiAIoCEICyAIC8EBAQJ/IwBBEGsiASQAAkACQAJAIAC9QiCIp0H/////B3EiAkH7w6T/A0sNACACQf////EDSw0BIAEgAEQAAAAAAABwOKIgAEQAAAAAAABwR6AgAkGAgMAASRs5AwAgAUEQaiQAIAAPCyACQYCAwP8HSQ0BIAFBEGokACAAIAChDwsgAEQAAAAAAAAAAEEAEBYhACABQRBqJAAgAA8LIAAgARAJIQIgASsDACABKwMIIAJBAXEQFiEAIAFBEGokACAAC4ACAwF/An4BfyMAQRBrIgEkACAAvSICQv///////////wCDIgO/IQACQAJAAkACQCADQiCIpyIEQeunhv8DSQ0AIARBgYDQgQRJDQFEAAAAAAAAAIAgAKNEAAAAAAAA8D+gIQAMAwsgBEGvscH+A0kNASAAIACgEA8iACAARAAAAAAAAABAoKMhAAwCC0QAAAAAAADwP0QAAAAAAAAAQCAAIACgEA9EAAAAAAAAAECgo6EhAAwBCwJAIARBgIDAAEkNACAARAAAAAAAAADAohAPIgCaIABEAAAAAAAAAECgoyEADAELIAEgALY4AgwLIAFBEGokACAAmiAAIAJCAFMbC/wCAgN/AX4CQCACRQ0AIAAgAToAACAAIAJqIgNBf2ogAToAACACQQNJDQAgACABOgACIAAgAToAASADQX1qIAE6AAAgA0F+aiABOgAAIAJBB0kNACAAIAE6AAMgA0F8aiABOgAAIAJBCUkNACAAQQAgAGtBA3EiBGoiAyABQf8BcUGBgoQIbCIBNgIAIAMgAiAEa0F8cSIEaiICQXxqIAE2AgAgBEEJSQ0AIAMgATYCCCADIAE2AgQgAkF4aiABNgIAIAJBdGogATYCACAEQRlJDQAgAyABNgIQIAMgATYCDCADIAE2AhQgAyABNgIYIAJBaGogATYCACACQWRqIAE2AgAgAkFsaiABNgIAIAJBcGogATYCACAEIANBBHFBGHIiBWsiAkEgSQ0AIAGtIgZCIIYgBoQhBiADIAVqIQEDQCABIAY3AwAgAUEIaiAGNwMAIAFBEGogBjcDACABQRhqIAY3AwAgAUEgaiEBIAJBYGoiAkEfSw0ACwsgAAsLqBcBAEGACAugF0+7YQVnrN0/GC1EVPsh6T+b9oHSC3PvPxgtRFT7Ifk/4mUvIn8rejwHXBQzJqaBPL3L8HqIB3A8B1wUMyamkTwDAAAABAAAAAQAAAAGAAAAg/miAERObgD8KRUA0VcnAN009QBi28AAPJmVAEGQQwBjUf4Au96rALdhxQA6biQA0k1CAEkG4AAJ6i4AHJLRAOsd/gApsRwA6D6nAPU1ggBEuy4AnOmEALQmcABBfl8A1pE5AFODOQCc9DkAi1+EACj5vQD4HzsA3v+XAA+YBQARL+8AClqLAG0fbQDPfjYACcsnAEZPtwCeZj8ALepfALondQDl68cAPXvxAPc5BwCSUooA+2vqAB+xXwAIXY0AMANWAHv8RgDwq2sAILzPADb0mgDjqR0AXmGRAAgb5gCFmWUAoBRfAI1AaACA2P8AJ3NNAAYGMQDKVhUAyahzAHviYABrjMAAGcRHAM1nwwAJ6NwAWYMqAIt2xACmHJYARK/dABlX0QClPgUABQf/ADN+PwDCMugAmE/eALt9MgAmPcMAHmvvAJ/4XgA1HzoAf/LKAPGHHQB8kCEAaiR8ANVu+gAwLXcAFTtDALUUxgDDGZ0ArcTCACxNQQAMAF0Ahn1GAONxLQCbxpoAM2IAALTSfAC0p5cAN1XVANc+9gCjEBgATXb8AGSdKgBw16sAY3z4AHqwVwAXFecAwElWADvW2QCnhDgAJCPLANaKdwBaVCMAAB+5APEKGwAZzt8AnzH/AGYeagCZV2EArPtHAH5/2AAiZbcAMuiJAOa/YADvxM0AbDYJAF0/1AAW3tcAWDveAN6bkgDSIigAKIboAOJYTQDGyjIACOMWAOB9ywAXwFAA8x2nABjgWwAuEzQAgxJiAINIAQD1jlsArbB/AB7p8gBISkMAEGfTAKrd2ACuX0IAamHOAAoopADTmbQABqbyAFx3fwCjwoMAYTyIAIpzeACvjFoAb9e9AC2mYwD0v8sAjYHvACbBZwBVykUAytk2ACio0gDCYY0AEsl3AAQmFAASRpsAxFnEAMjFRABNspEAABfzANRDrQApSeUA/dUQAAC+/AAelMwAcM7uABM+9QDs8YAAs+fDAMf4KACTBZQAwXE+AC4JswALRfMAiBKcAKsgewAutZ8AR5LCAHsyLwAMVW0AcqeQAGvnHwAxy5YAeRZKAEF54gD034kA6JSXAOLmhACZMZcAiO1rAF9fNgC7/Q4ASJq0AGekbABxckIAjV0yAJ8VuAC85QkAjTElAPd0OQAwBRwADQwBAEsIaAAs7lgAR6qQAHTnAgC91iQA932mAG5IcgCfFu8AjpSmALSR9gDRU1EAzwryACCYMwD1S34AsmNoAN0+XwBAXQMAhYl/AFVSKQA3ZMAAbdgQADJIMgBbTHUATnHUAEVUbgALCcEAKvVpABRm1QAnB50AXQRQALQ72wDqdsUAh/kXAElrfQAdJ7oAlmkpAMbMrACtFFQAkOJqAIjZiQAsclAABKS+AHcHlADzMHAAAPwnAOpxqABmwkkAZOA9AJfdgwCjP5cAQ5T9AA2GjAAxQd4AkjmdAN1wjAAXt+cACN87ABU3KwBcgKAAWoCTABARkgAP6NgAbICvANv/SwA4kA8AWRh2AGKlFQBhy7sAx4m5ABBAvQDS8gQASXUnAOu29gDbIrsAChSqAIkmLwBkg3YACTszAA6UGgBROqoAHaPCAK/trgBcJhIAbcJNAC16nADAVpcAAz+DAAnw9gArQIwAbTGZADm0BwAMIBUA2MNbAPWSxADGrUsATsqlAKc3zQDmqTYAq5KUAN1CaAAZY94AdozvAGiLUgD82zcArqGrAN8VMQAArqEADPvaAGRNZgDtBbcAKWUwAFdWvwBH/zoAavm5AHW+8wAok98Aq4AwAGaM9gAEyxUA+iIGANnkHQA9s6QAVxuPADbNCQBOQukAE76kADMjtQDwqhoAT2WoANLBpQALPw8AW3jNACP5dgB7iwQAiRdyAMamUwBvbuIA7+sAAJtKWADE2rcAqma6AHbPzwDRAh0AsfEtAIyZwQDDrXcAhkjaAPddoADGgPQArPAvAN3smgA/XLwA0N5tAJDHHwAq27YAoyU6AACvmgCtU5MAtlcEACkttABLgH4A2genAHaqDgB7WaEAFhIqANy3LQD65f0Aidv+AIm+/QDkdmwABqn8AD6AcACFbhUA/Yf/ACg+BwBhZzMAKhiGAE296gCz568Aj21uAJVnOQAxv1sAhNdIADDfFgDHLUMAJWE1AMlwzgAwy7gAv2z9AKQAogAFbOQAWt2gACFvRwBiEtIAuVyEAHBhSQBrVuAAmVIBAFBVNwAe1bcAM/HEABNuXwBdMOQAhS6pAB2ywwChMjYACLekAOqx1AAW9yEAj2nkACf/dwAMA4AAjUAtAE/NoAAgpZkAs6LTAC9dCgC0+UIAEdrLAH2+0ACb28EAqxe9AMqigQAIalwALlUXACcAVQB/FPAA4QeGABQLZACWQY0Ah77eANr9KgBrJbYAe4k0AAXz/gC5v54AaGpPAEoqqABPxFoALfi8ANdamAD0x5UADU2NACA6pgCkV18AFD+xAIA4lQDMIAEAcd2GAMnetgC/YPUATWURAAEHawCMsKwAssDQAFFVSAAe+w4AlXLDAKMGOwDAQDUABtx7AOBFzABOKfoA1srIAOjzQQB8ZN4Am2TYANm+MQCkl8MAd1jUAGnjxQDw2hMAujo8AEYYRgBVdV8A0r31AG6SxgCsLl0ADkTtABw+QgBhxIcAKf3pAOfW8wAifMoAb5E1AAjgxQD/140AbmriALD9xgCTCMEAfF10AGutsgDNbp0APnJ7AMYRagD3z6kAKXPfALXJugC3AFEA4rINAHS6JADlfWAAdNiKAA0VLACBGAwAfmaUAAEpFgCfenYA/f2+AFZF7wDZfjYA7NkTAIu6uQDEl/wAMagnAPFuwwCUxTYA2KhWALSotQDPzA4AEoktAG9XNAAsVokAmc7jANYguQBrXqoAPiqcABFfzAD9C0oA4fT7AI47bQDihiwA6dSEAPy0qQDv7tEALjXJAC85YQA4IUQAG9nIAIH8CgD7SmoALxzYAFO0hABOmYwAVCLMACpV3ADAxtYACxmWABpwuABplWQAJlpgAD9S7gB/EQ8A9LURAPzL9QA0vC0ANLzuAOhdzADdXmAAZ46bAJIz7wDJF7gAYVibAOFXvABRg8YA2D4QAN1xSAAtHN0ArxihACEsRgBZ89cA2XqYAJ5UwABPhvoAVgb8AOV5rgCJIjYAOK0iAGeT3ABV6KoAgiY4AMrnmwBRDaQAmTOxAKnXDgBpBUgAZbLwAH+IpwCITJcA+dE2ACGSswB7gkoAmM8hAECf3ADcR1UA4XQ6AGfrQgD+nd8AXtRfAHtnpAC6rHoAVfaiACuIIwBBulUAWW4IACEqhgA5R4MAiePmAOWe1ABJ+0AA/1bpABwPygDFWYoAlPorANPBxQAPxc8A21quAEfFhgCFQ2IAIYY7ACx5lAAQYYcAKkx7AIAsGgBDvxIAiCaQAHg8iQCoxOQA5dt7AMQ6wgAm9OoA92eKAA2SvwBloysAPZOxAL18CwCkUdwAJ91jAGnh3QCalBkAqCmVAGjOKAAJ7bQARJ8gAE6YygBwgmMAfnwjAA+5MgCn9Y4AFFbnACHxCAC1nSoAb35NAKUZUQC1+asAgt/WAJbdYQAWNgIAxDqfAIOioQBy7W0AOY16AIK4qQBrMlwARidbAAA07QDSAHcA/PRVAAFZTQDgcYAAAAAAAAAAAAAAAABA+yH5PwAAAAAtRHQ+AAAAgJhG+DwAAABgUcx4OwAAAICDG/A5AAAAQCAlejgAAACAIoLjNgAAAAAd82k1AAAAAAAA4D8AAAAAAADgvwAAAAAAAPA/AAAAAAAA+D8AAAAAAAAAAAbQz0Pr/Uw+AAAAAAAAAAAAAABAA7jiPwDsBwRuYW1lAcUBGgARX193YXNtX2NhbGxfY3RvcnMBBGFjb3MCBWFjb3NoAwRhc2luBAVhc2luaAUEYXRhbgYFYXRhbmgHBV9fY29zCBBfX3JlbV9waW8yX2xhcmdlCQpfX3JlbV9waW8yCgVfX3NpbgsDY29zDAdfX2V4cG8yDQRjb3NoDgNleHAPBWV4cG0xEANsb2cRBWxvZzFwEgNwb3cTBnNjYWxibhQDc2luFQRzaW5oFgVfX3RhbhcDdGFuGAR0YW5oGQZtZW1zZXQCnAYaAAABBQACcDABAmwwAgJsMQMCbDIEAmwzAgIAAnAwAQJsMAMGAAJwMAECbDACAmwxAwJsMgQCbDMFAmw0BAUAAnAwAQJsMAICbDEDAmwyBAJsMwUIAAJwMAECbDACAmwxAwJsMgQCbDMFAmw0BgJsNQcCbDYGBQACcDABAmwwAgJsMQMCbDIEAmwzBwUAAnAwAQJwMQICbDADAmwxBAJsMggdAAJwMAECcDECAnAyAwJwMwQCcDQFAmwwBgJsMQcCbDIIAmwzCQJsNAoCbDULAmw2DAJsNw0CbDgOAmw5DwNsMTAQA2wxMREDbDEyEgNsMTMTA2wxNBQDbDE1FQNsMTYWA2wxNxcDbDE4GANsMTkZA2wyMBoDbDIxGwNsMjIcA2wyMwkMAAJwMAECcDECAmwwAwJsMQQCbDIFAmwzBgJsNAcCbDUIAmw2CQJsNwoCbDgLAmw5CgYAAnAwAQJwMQICcDIDAmwwBAJsMQUCbDILBAACcDABAmwwAgJsMQMCbDIMAQACcDANBAACcDABAmwwAgJsMQMCbDIOCAACcDABAmwwAgJsMQMCbDIEAmwzBQJsNAYCbDUHAmw2DwkAAnAwAQJsMAICbDEDAmwyBAJsMwUCbDQGAmw1BwJsNggCbDcQBwACcDABAmwwAgJsMQMCbDIEAmwzBQJsNAYCbDURBwACcDABAmwwAgJsMQMCbDIEAmwzBQJsNAYCbDUSFQACcDABAnAxAgJsMAMCbDEEAmwyBQJsMwYCbDQHAmw1CAJsNgkCbDcKAmw4CwJsOQwDbDEwDQNsMTEOA2wxMg8DbDEzEANsMTQRA2wxNRIDbDE2EwNsMTcUA2wxOBMDAAJwMAECcDECAmwwFAQAAnAwAQJsMAICbDEDAmwyFQUAAnAwAQJsMAICbDEDAmwyBAJsMxYJAAJwMAECcDECAnAyAwJsMAQCbDEFAmwyBgJsMwcCbDQIAmw1FwMAAnAwAQJsMAICbDEYBQACcDABAmwwAgJsMQMCbDIEAmwzGQcAAnAwAQJwMQICcDIDAmwwBAJsMQUCbDIGAmwz" diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt new file mode 100644 index 000000000..822dedc3a --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt @@ -0,0 +1,77 @@ +package space.kscience.kmath.wasm + +import space.kscience.kmath.estree.compileWith +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.wasm.internal.DoubleWasmBuilder +import space.kscience.kmath.wasm.internal.IntWasmBuilder + +/** + * Compiles an [MST] to WASM in the context of reals. + * + * @author Iaroslav Postovalov + */ +public fun DoubleField.expression(mst: MST): Expression = + DoubleWasmBuilder(mst).instance + +/** + * Compiles an [MST] to WASM in the context of integers. + * + * @author Iaroslav Postovalov + */ +public fun IntRing.expression(mst: MST): Expression = + IntWasmBuilder(mst).instance + +/** + * Create a compiled expression with given [MST] and given [algebra]. + * + * @author Iaroslav Postovalov + */ +public fun MST.compileToExpression(algebra: IntRing): Expression = compileWith(algebra) + + +/** + * Compile given MST to expression and evaluate it against [arguments]. + * + * @author Iaroslav Postovalov + */ +public fun MST.compile(algebra: IntRing, arguments: Map): Int = + compileToExpression(algebra).invoke(arguments) + + +/** + * Compile given MST to expression and evaluate it against [arguments]. + * + * @author Iaroslav Postovalov + */ +public fun MST.compile(algebra: IntRing, vararg arguments: Pair): Int = + compileToExpression(algebra)(*arguments) + +/** + * Create a compiled expression with given [MST] and given [algebra]. + * + * @author Iaroslav Postovalov + */ +public fun MST.compileToExpression(algebra: DoubleField): Expression = compileWith(algebra) + + +/** + * Compile given MST to expression and evaluate it against [arguments]. + * + * @author Iaroslav Postovalov + */ +public fun MST.compile(algebra: DoubleField, arguments: Map): Double = + compileToExpression(algebra).invoke(arguments) + + +/** + * Compile given MST to expression and evaluate it against [arguments]. + * + * @author Iaroslav Postovalov + */ +public fun MST.compile(algebra: DoubleField, vararg arguments: Pair): Double = + compileToExpression(algebra).invoke(*arguments) diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt new file mode 100644 index 000000000..634a89b26 --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt @@ -0,0 +1,67 @@ +package space.kscience.kmath.ast + +import space.kscience.kmath.expressions.* +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.math.sin +import kotlin.random.Random +import kotlin.test.Test +import kotlin.time.measureTime +import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression +import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression + +internal class TestExecutionTime { + private companion object { + private const val times = 1_000_000 + private val x by symbol + private val algebra: ExtendedField = DoubleField + + private val functional = DoubleField.expressionInExtendedField { + bindSymbol(x) * const(2.0) + const(2.0) / bindSymbol(x) - const(16.0) / sin(bindSymbol(x)) + } + + private val node = MstExtendedField { + bindSymbol(x) * number(2.0) + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x)) + } + + private val mst = node.toExpression(DoubleField) + private val wasm = node.wasmCompileToExpression(DoubleField) + private val estree = node.estreeCompileToExpression(DoubleField) + + // In JavaScript, the expression below is implemented like + // _no_name_provided__125.prototype.invoke_178 = function (args) { + // var tmp = getValue(args, raw$_get_x__3(this._$x$delegate_2)) * 2.0 + 2.0 / getValue(args, raw$_get_x__3(this._$x$delegate_2)); + // var tmp0_sin_0_5 = getValue(args, raw$_get_x__3(this._$x$delegate_2)); + // return tmp - 16.0 / Math.sin(tmp0_sin_0_5); + // }; + + private val raw = Expression { args -> + args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 / sin(args.getValue(x)) + } + } + + private fun invokeAndSum(name: String, expr: Expression) { + println(name) + val rng = Random(0) + var sum = 0.0 + measureTime { repeat(times) { sum += expr(x to rng.nextDouble()) } }.also(::println) + } + + @Test + fun functionalExpression() = invokeAndSum("functional", functional) + + @Test + fun mstExpression() = invokeAndSum("mst", mst) + + @Test + fun wasmExpression() = invokeAndSum("wasm", wasm) + + @Test + fun estreeExpression() = invokeAndSum("estree", wasm) + + @Test + fun rawExpression() = invokeAndSum("raw", raw) +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt index 5823518ce..d80318db8 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt @@ -8,18 +8,17 @@ package space.kscience.kmath.estree import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.toComplex import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals internal class TestESTreeConsistencyWithInterpreter { - @Test fun mstSpace() { - val mst = MstGroup { binaryOperationFunction("+")( unaryOperationFunction("+")( @@ -30,12 +29,12 @@ internal class TestESTreeConsistencyWithInterpreter { ), number(1) - ) + bindSymbol("x") + zero + ) + bindSymbol(x) + zero } assertEquals( - mst.interpret(MstGroup, Symbol.x to MST.Numeric(2)), - mst.compile(MstGroup, Symbol.x to MST.Numeric(2)) + mst.interpret(MstGroup, x to MST.Numeric(2)), + mst.compile(MstGroup, x to MST.Numeric(2)) ) } @@ -44,7 +43,7 @@ internal class TestESTreeConsistencyWithInterpreter { val mst = MstRing { binaryOperationFunction("+")( unaryOperationFunction("+")( - (bindSymbol("x") - (2.toByte() + (scale( + (bindSymbol(x) - (2.toByte() + (scale( add(number(1), number(1)), 2.0 ) + 1.toByte()))) * 3.0 - 1.toByte() @@ -55,24 +54,24 @@ internal class TestESTreeConsistencyWithInterpreter { } assertEquals( - mst.interpret(ByteRing, Symbol.x to 3.toByte()), - mst.compile(ByteRing, Symbol.x to 3.toByte()) + mst.interpret(ByteRing, x to 3.toByte()), + mst.compile(ByteRing, x to 3.toByte()) ) } @Test - fun realField() { + fun doubleField() { val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero } assertEquals( - mst.interpret(DoubleField, Symbol.x to 2.0), - mst.compile(DoubleField, Symbol.x to 2.0) + mst.interpret(DoubleField, x to 2.0), + mst.compile(DoubleField, x to 2.0) ) } @@ -80,15 +79,19 @@ internal class TestESTreeConsistencyWithInterpreter { fun complexField() { val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero } assertEquals( - mst.interpret(ComplexField, Symbol.x to 2.0.toComplex()), - mst.compile(ComplexField, Symbol.x to 2.0.toComplex()) + mst.interpret(ComplexField, x to 2.0.toComplex()), + mst.compile(ComplexField, x to 2.0.toComplex()), ) } + + private companion object { + private val x by symbol + } } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt index a1bff92d0..a0b68a811 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt @@ -5,43 +5,38 @@ package space.kscience.kmath.estree -import space.kscience.kmath.expressions.MstExtendedField +import space.kscience.kmath.expressions.MstField +import space.kscience.kmath.expressions.MstGroup import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke -import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals internal class TestESTreeOperationsSupport { @Test fun testUnaryOperationInvocation() { - val expression = MstExtendedField { -bindSymbol("x") }.compileToExpression(DoubleField) - val res = expression("x" to 2.0) + val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField) + val res = expression(x to 2.0) assertEquals(-2.0, res) } @Test fun testBinaryOperationInvocation() { - val expression = MstExtendedField { -bindSymbol("x") + number(1.0) }.compileToExpression(DoubleField) - val res = expression("x" to 2.0) + val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField) + val res = expression(x to 2.0) assertEquals(-1.0, res) } @Test fun testConstProductInvocation() { - val res = MstExtendedField { bindSymbol("x") * 2 }.compileToExpression(DoubleField)("x" to 2.0) + val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0) assertEquals(4.0, res) } - @Test - fun testMultipleCalls() { - val e = - MstExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } - .compileToExpression(DoubleField) - val r = Random(0) - var s = 0.0 - repeat(1000000) { s += e("x" to r.nextDouble()) } - println(s) + private companion object { + private val x by symbol } } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt index b5ae1ca3f..6756fd8c7 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt @@ -7,7 +7,9 @@ package space.kscience.kmath.estree import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals @@ -15,55 +17,60 @@ import kotlin.test.assertEquals internal class TestESTreeSpecialization { @Test fun testUnaryPlus() { - val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol("x")) }.compileToExpression(DoubleField) - assertEquals(2.0, expr("x" to 2.0)) + val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(2.0, expr(x to 2.0)) } @Test fun testUnaryMinus() { - val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol("x")) }.compileToExpression(DoubleField) - assertEquals(-2.0, expr("x" to 2.0)) + val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(-2.0, expr(x to 2.0)) } @Test fun testAdd() { val expr = MstExtendedField { - binaryOperationFunction("+")(bindSymbol("x"), - bindSymbol("x")) + binaryOperationFunction("+")( + bindSymbol(x), + bindSymbol(x), + ) }.compileToExpression(DoubleField) - assertEquals(4.0, expr("x" to 2.0)) + assertEquals(4.0, expr(x to 2.0)) } @Test fun testSine() { - val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol("x")) }.compileToExpression(DoubleField) - assertEquals(0.0, expr("x" to 0.0)) + val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(0.0, expr(x to 0.0)) } @Test - fun testMinus() { + fun testSubtract() { val expr = MstExtendedField { - binaryOperationFunction("-")(bindSymbol("x"), - bindSymbol("x")) + binaryOperationFunction("-")(bindSymbol(x), + bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(0.0, expr("x" to 2.0)) + assertEquals(0.0, expr(x to 2.0)) } @Test fun testDivide() { val expr = MstExtendedField { - binaryOperationFunction("/")(bindSymbol("x"), - bindSymbol("x")) + binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(1.0, expr("x" to 2.0)) + assertEquals(1.0, expr(x to 2.0)) } @Test fun testPower() { val expr = MstExtendedField { - binaryOperationFunction("pow")(bindSymbol("x"), number(2)) + binaryOperationFunction("pow")(bindSymbol(x), number(2)) }.compileToExpression(DoubleField) - assertEquals(4.0, expr("x" to 2.0)) + assertEquals(4.0, expr(x to 2.0)) + } + + private companion object { + private val x by symbol } } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt index 1effe14e1..e1830d9df 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt @@ -7,7 +7,9 @@ package space.kscience.kmath.estree import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.ByteRing +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals @@ -16,13 +18,17 @@ import kotlin.test.assertFailsWith internal class TestESTreeVariables { @Test fun testVariable() { - val expr = MstRing{ bindSymbol("x") }.compileToExpression(ByteRing) - assertEquals(1.toByte(), expr("x" to 1.toByte())) + val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) + assertEquals(1.toByte(), expr(x to 1.toByte())) } @Test fun testUndefinedVariableFails() { - val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing) + val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) assertFailsWith { expr() } } + + private companion object { + private val x by symbol + } } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt new file mode 100644 index 000000000..f3e0726d6 --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.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.wasm + +import space.kscience.kmath.expressions.MstField +import space.kscience.kmath.expressions.MstRing +import space.kscience.kmath.expressions.interpret +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class TestWasmConsistencyWithInterpreter { + @Test + fun intRing() { + val mst = MstRing { + binaryOperationFunction("+")( + unaryOperationFunction("+")( + (bindSymbol(x) - (2.toByte() + (scale( + add(number(1), number(1)), + 2.0 + ) + 1.toByte()))) * 3.0 - 1.toByte() + ), + + number(1) + ) * number(2) + } + + assertEquals( + mst.interpret(IntRing, x to 3), + mst.compile(IntRing, x to 3) + ) + } + + @Test + fun doubleField() { + val mst = MstField { + +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( + (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + + number(1), + number(1) / 2 + number(2.0) * one + ) + zero + } + + assertEquals( + mst.interpret(DoubleField, x to 2.0), + mst.compile(DoubleField, x to 2.0) + ) + } + + private companion object { + private val x by symbol + } +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt new file mode 100644 index 000000000..2946592f4 --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt @@ -0,0 +1,42 @@ +/* + * 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.wasm + +import space.kscience.kmath.expressions.MstField +import space.kscience.kmath.expressions.MstGroup +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class TestWasmOperationsSupport { + @Test + fun testUnaryOperationInvocation() { + val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField) + val res = expression(x to 2.0) + assertEquals(-2.0, res) + } + + @Test + fun testBinaryOperationInvocation() { + val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField) + val res = expression(x to 2.0) + assertEquals(-1.0, res) + } + + @Test + fun testConstProductInvocation() { + val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0) + assertEquals(4.0, res) + } + + private companion object { + private val x by symbol + } +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt new file mode 100644 index 000000000..e1f7b603a --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt @@ -0,0 +1,76 @@ +/* + * 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.wasm + +import space.kscience.kmath.expressions.MstExtendedField +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class TestWasmSpecialization { + @Test + fun testUnaryPlus() { + val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(2.0, expr(x to 2.0)) + } + + @Test + fun testUnaryMinus() { + val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(-2.0, expr(x to 2.0)) + } + + @Test + fun testAdd() { + val expr = MstExtendedField { + binaryOperationFunction("+")( + bindSymbol(x), + bindSymbol(x), + ) + }.compileToExpression(DoubleField) + assertEquals(4.0, expr(x to 2.0)) + } + + @Test + fun testSine() { + val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(0.0, expr(x to 0.0)) + } + + @Test + fun testSubtract() { + val expr = MstExtendedField { + binaryOperationFunction("-")(bindSymbol(x), + bindSymbol(x)) + }.compileToExpression(DoubleField) + assertEquals(0.0, expr(x to 2.0)) + } + + @Test + fun testDivide() { + val expr = MstExtendedField { + binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x)) + }.compileToExpression(DoubleField) + assertEquals(1.0, expr(x to 2.0)) + } + + @Test + fun testPower() { + val expr = MstExtendedField { + binaryOperationFunction("pow")(bindSymbol(x), number(2)) + }.compileToExpression(DoubleField) + + assertEquals(4.0, expr(x to 2.0)) + } + + private companion object { + private val x by symbol + } +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt new file mode 100644 index 000000000..e627f551c --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt @@ -0,0 +1,48 @@ +package space.kscience.kmath.wasm + +import space.kscience.kmath.expressions.MstExtendedField +import space.kscience.kmath.expressions.MstRing +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class TestWasmSpecific { + @Test + fun int() { + val res = MstRing { number(100000000) + number(10000000) }.compile(IntRing) + assertEquals(110000000, res) + } + + @Test + fun real() { + val res = MstExtendedField { number(100000000) + number(2).pow(10) }.compile(DoubleField) + assertEquals(100001024.0, res) + } + + @Test + fun argsPassing() { + val res = MstExtendedField { bindSymbol(y) + bindSymbol(x).pow(10) }.compile( + DoubleField, + x to 2.0, + y to 100000000.0, + ) + + assertEquals(100001024.0, res) + } + + @Test + fun powFunction() { + val expr = MstExtendedField { bindSymbol(x).pow(1.0 / 6.0) }.compileToExpression(DoubleField) + assertEquals(0.9730585187140817, expr(x to 0.8488554755054833)) + } + + private companion object { + private val x by symbol + private val y by symbol + } +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt new file mode 100644 index 000000000..406ba8c8d --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt @@ -0,0 +1,34 @@ +/* + * 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.wasm + +import space.kscience.kmath.expressions.MstRing +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +internal class TestWasmVariables { + @Test + fun testVariable() { + val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing) + assertEquals(1, expr(x to 1)) + } + + @Test + fun testUndefinedVariableFails() { + val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing) + assertFailsWith { expr() } + } + + private companion object { + private val x by symbol + } +} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt index 77cfb2241..f94d36602 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt @@ -8,18 +8,17 @@ package space.kscience.kmath.asm import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.toComplex import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.Symbol.Companion.x +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals internal class TestAsmConsistencyWithInterpreter { - @Test fun mstSpace() { - val mst = MstGroup { binaryOperationFunction("+")( unaryOperationFunction("+")( @@ -30,7 +29,7 @@ internal class TestAsmConsistencyWithInterpreter { ), number(1) - ) + bindSymbol("x") + zero + ) + bindSymbol(x) + zero } assertEquals( @@ -44,7 +43,7 @@ internal class TestAsmConsistencyWithInterpreter { val mst = MstRing { binaryOperationFunction("+")( unaryOperationFunction("+")( - (bindSymbol("x") - (2.toByte() + (scale( + (bindSymbol(x) - (2.toByte() + (scale( add(number(1), number(1)), 2.0 ) + 1.toByte()))) * 3.0 - 1.toByte() @@ -61,10 +60,10 @@ internal class TestAsmConsistencyWithInterpreter { } @Test - fun realField() { + fun doubleField() { val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero @@ -80,7 +79,7 @@ internal class TestAsmConsistencyWithInterpreter { fun complexField() { val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one ) + zero @@ -91,4 +90,8 @@ internal class TestAsmConsistencyWithInterpreter { mst.compile(ComplexField, x to 2.0.toComplex()) ) } + + private companion object { + private val x by symbol + } } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt index 757235fb7..147639f7c 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt @@ -5,45 +5,38 @@ package space.kscience.kmath.asm -import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.MstField import space.kscience.kmath.expressions.MstGroup import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke -import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals internal class TestAsmOperationsSupport { @Test fun testUnaryOperationInvocation() { - val expression = MstGroup { -bindSymbol("x") }.compileToExpression(DoubleField) - val res = expression("x" to 2.0) + val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField) + val res = expression(x to 2.0) assertEquals(-2.0, res) } @Test fun testBinaryOperationInvocation() { - val expression = MstGroup { -bindSymbol("x") + number(1.0) }.compileToExpression(DoubleField) - val res = expression("x" to 2.0) + val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField) + val res = expression(x to 2.0) assertEquals(-1.0, res) } @Test fun testConstProductInvocation() { - val res = MstField { bindSymbol("x") * 2 }.compileToExpression(DoubleField)("x" to 2.0) + val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0) assertEquals(4.0, res) } - @Test - fun testMultipleCalls() { - val e = - MstExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) } - .compileToExpression(DoubleField) - val r = Random(0) - var s = 0.0 - repeat(1000000) { s += e("x" to r.nextDouble()) } - println(s) + private companion object { + private val x by symbol } } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt index b09d79515..3a681e482 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt @@ -7,7 +7,9 @@ package space.kscience.kmath.asm import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals @@ -15,55 +17,60 @@ import kotlin.test.assertEquals internal class TestAsmSpecialization { @Test fun testUnaryPlus() { - val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol("x")) }.compileToExpression(DoubleField) - assertEquals(2.0, expr("x" to 2.0)) + val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(2.0, expr(x to 2.0)) } @Test fun testUnaryMinus() { - val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol("x")) }.compileToExpression(DoubleField) - assertEquals(-2.0, expr("x" to 2.0)) + val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(-2.0, expr(x to 2.0)) } @Test fun testAdd() { val expr = MstExtendedField { - binaryOperationFunction("+")(bindSymbol("x"), - bindSymbol("x")) + binaryOperationFunction("+")( + bindSymbol(x), + bindSymbol(x), + ) }.compileToExpression(DoubleField) - assertEquals(4.0, expr("x" to 2.0)) + assertEquals(4.0, expr(x to 2.0)) } @Test fun testSine() { - val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol("x")) }.compileToExpression(DoubleField) - assertEquals(0.0, expr("x" to 0.0)) + val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(0.0, expr(x to 0.0)) } @Test - fun testMinus() { + fun testSubtract() { val expr = MstExtendedField { - binaryOperationFunction("-")(bindSymbol("x"), - bindSymbol("x")) + binaryOperationFunction("-")(bindSymbol(x), + bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(0.0, expr("x" to 2.0)) + assertEquals(0.0, expr(x to 2.0)) } @Test fun testDivide() { val expr = MstExtendedField { - binaryOperationFunction("/")(bindSymbol("x"), - bindSymbol("x")) + binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(1.0, expr("x" to 2.0)) + assertEquals(1.0, expr(x to 2.0)) } @Test fun testPower() { val expr = MstExtendedField { - binaryOperationFunction("pow")(bindSymbol("x"), number(2)) + binaryOperationFunction("pow")(bindSymbol(x), number(2)) }.compileToExpression(DoubleField) - assertEquals(4.0, expr("x" to 2.0)) + assertEquals(4.0, expr(x to 2.0)) + } + + private companion object { + private val x by symbol } } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt index 740326a59..89b98d720 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt @@ -7,7 +7,9 @@ package space.kscience.kmath.asm import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.ByteRing +import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals @@ -16,13 +18,17 @@ import kotlin.test.assertFailsWith internal class TestAsmVariables { @Test fun testVariable() { - val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing) - assertEquals(1.toByte(), expr("x" to 1.toByte())) + val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) + assertEquals(1.toByte(), expr(x to 1.toByte())) } @Test fun testUndefinedVariableFails() { - val expr = MstRing { bindSymbol("x") }.compileToExpression(ByteRing) + val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) assertFailsWith { expr() } } + + private companion object { + private val x by symbol + } } diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt deleted file mode 100644 index 1584293ce..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.ast.rendering - -import space.kscience.kmath.ast.rendering.TestUtils.testLatex -import space.kscience.kmath.expressions.MST.Numeric -import kotlin.test.Test - -internal class TestFeatures { - @Test - fun printSymbolic() = testLatex("x", "x") - - @Test - fun printNumeric() { - val num = object : Number() { - override fun toByte(): Byte = throw UnsupportedOperationException() - override fun toChar(): Char = throw UnsupportedOperationException() - override fun toDouble(): Double = throw UnsupportedOperationException() - override fun toFloat(): Float = throw UnsupportedOperationException() - override fun toInt(): Int = throw UnsupportedOperationException() - override fun toLong(): Long = throw UnsupportedOperationException() - override fun toShort(): Short = throw UnsupportedOperationException() - override fun toString(): String = "foo" - } - - testLatex(Numeric(num), "foo") - } - - @Test - fun prettyPrintFloats() { - testLatex(Numeric(Double.NaN), "NaN") - testLatex(Numeric(Double.POSITIVE_INFINITY), "\\infty") - testLatex(Numeric(Double.NEGATIVE_INFINITY), "-\\infty") - testLatex(Numeric(1.0), "1") - testLatex(Numeric(-1.0), "-1") - testLatex(Numeric(1.42), "1.42") - testLatex(Numeric(-1.42), "-1.42") - testLatex(Numeric(1.1e10), "1.1\\times10^{10}") - testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}") - testLatex(Numeric(-1.1e-10), "-1.1\\times10^{-10}") - testLatex(Numeric(-1.1e10), "-1.1\\times10^{10}") - } - - @Test - fun prettyPrintIntegers() { - testLatex(Numeric(42), "42") - testLatex(Numeric(-42), "-42") - } - - @Test - fun prettyPrintPi() { - testLatex("pi", "\\pi") - } - - @Test - fun binaryPlus() = testLatex("2+2", "2+2") - - @Test - fun binaryMinus() = testLatex("2-2", "2-2") - - @Test - fun fraction() = testLatex("2/2", "\\frac{2}{2}") - - @Test - fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)") - - @Test - fun unaryOperator() = testLatex("f(x)", "\\operatorname{f}\\,\\left(x\\right)") - - @Test - fun power() = testLatex("x^y", "x^{y}") - - @Test - fun squareRoot() = testLatex("sqrt(x)", "\\sqrt{x}") - - @Test - fun exponential() = testLatex("exp(x)", "e^{x}") - - @Test - fun multiplication() = testLatex("x*1", "x\\times1") - - @Test - fun inverseTrigonometry() { - testLatex("asin(x)", "\\operatorname{sin}^{-1}\\,\\left(x\\right)") - testLatex("asinh(x)", "\\operatorname{sinh}^{-1}\\,\\left(x\\right)") - testLatex("acos(x)", "\\operatorname{cos}^{-1}\\,\\left(x\\right)") - testLatex("acosh(x)", "\\operatorname{cosh}^{-1}\\,\\left(x\\right)") - testLatex("atan(x)", "\\operatorname{tan}^{-1}\\,\\left(x\\right)") - testLatex("atanh(x)", "\\operatorname{tanh}^{-1}\\,\\left(x\\right)") - } - -// @Test -// fun unaryPlus() { -// testLatex("+1", "+1") -// testLatex("+1", "++1") -// } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt deleted file mode 100644 index 6322df25d..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.ast.rendering - -import space.kscience.kmath.ast.rendering.TestUtils.testLatex -import space.kscience.kmath.expressions.MST -import space.kscience.kmath.operations.GroupOperations -import kotlin.test.Test - -internal class TestLatex { - @Test - fun number() = testLatex("42", "42") - - @Test - fun symbol() = testLatex("x", "x") - - @Test - fun operatorName() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") - - @Test - fun specialSymbol() { - testLatex(MST.Numeric(Double.POSITIVE_INFINITY), "\\infty") - testLatex("pi", "\\pi") - } - - @Test - fun operand() { - testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") - testLatex("1+1", "1+1") - } - - @Test - fun unaryOperator() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") - - @Test - fun unaryPlus() = testLatex(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1") - - @Test - fun unaryMinus() = testLatex("-x", "-x") - - @Test - fun radical() = testLatex("sqrt(x)", "\\sqrt{x}") - - @Test - fun superscript() = testLatex("x^y", "x^{y}") - - @Test - fun subscript() = testLatex(SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), "x_{123}") - - @Test - fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)") - - @Test - fun binaryPlus() = testLatex("x+x", "x+x") - - @Test - fun binaryMinus() = testLatex("x-x", "x-x") - - @Test - fun fraction() = testLatex("x/x", "\\frac{x}{x}") - - @Test - fun radicalWithIndex() = testLatex(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), "\\sqrt[x]{y}") - - @Test - fun multiplication() { - testLatex("x*1", "x\\times1") - testLatex("1*x", "1\\,x") - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt deleted file mode 100644 index 2d7bfad19..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.ast.rendering - -import space.kscience.kmath.ast.rendering.TestUtils.testMathML -import space.kscience.kmath.expressions.MST -import space.kscience.kmath.operations.GroupOperations -import kotlin.test.Test - -internal class TestMathML { - @Test - fun number() = testMathML("42", "42") - - @Test - fun symbol() = testMathML("x", "x") - - @Test - fun operatorName() = testMathML( - "sin(1)", - "sin1", - ) - - @Test - fun specialSymbol() { - testMathML(MST.Numeric(Double.POSITIVE_INFINITY), "") - testMathML("pi", "π") - } - - @Test - fun operand() { - testMathML( - "sin(1)", - "sin1", - ) - - testMathML("1+1", "1+1") - } - - @Test - fun unaryOperator() = testMathML( - "sin(1)", - "sin1", - ) - - @Test - fun unaryPlus() = - testMathML(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1") - - @Test - fun unaryMinus() = testMathML("-x", "-x") - - @Test - fun radical() = testMathML("sqrt(x)", "x") - - @Test - fun superscript() = testMathML("x^y", "xy") - - @Test - fun subscript() = testMathML( - SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), - "x123", - ) - - @Test - fun binaryOperator() = testMathML( - "f(x, y)", - "fx,y", - ) - - @Test - fun binaryPlus() = testMathML("x+x", "x+x") - - @Test - fun binaryMinus() = testMathML("x-x", "x-x") - - @Test - fun fraction() = testMathML("x/x", "xx") - - @Test - fun radicalWithIndex() = - testMathML(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), - "yx") - - @Test - fun multiplication() { - testMathML("x*1", "x×1") - testMathML("1*x", "1x") - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt deleted file mode 100644 index a4017fdb4..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.ast.rendering - -import space.kscience.kmath.ast.rendering.TestUtils.testLatex -import kotlin.test.Test - -internal class TestStages { - @Test - fun betterMultiplication() { - testLatex("a*1", "a\\times1") - testLatex("1*(2/3)", "1\\times\\left(\\frac{2}{3}\\right)") - testLatex("1*1", "1\\times1") - testLatex("2e10", "2\\times10^{10}") - testLatex("2*x", "2\\,x") - testLatex("2*(x+1)", "2\\,\\left(x+1\\right)") - testLatex("x*y", "x\\,y") - } - - @Test - fun parentheses() { - testLatex("(x+1)", "x+1") - testLatex("x*x*x", "x\\,x\\,x") - testLatex("(x+x)*x", "\\left(x+x\\right)\\,x") - testLatex("x+x*x", "x+x\\,x") - testLatex("x+x^x*x+x", "x+x^{x}\\,x+x") - testLatex("(x+x)^x+x*x", "\\left(x+x\\right)^{x}+x\\,x") - testLatex("x^(x+x)", "x^{x+x}") - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt deleted file mode 100644 index 7c9400532..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.ast.rendering - -import space.kscience.kmath.ast.parseMath -import space.kscience.kmath.expressions.MST -import kotlin.test.assertEquals - -internal object TestUtils { - private fun mathSyntax(mst: MST) = FeaturedMathRendererWithPostProcess.Default.render(mst) - private fun latex(mst: MST) = LatexSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst)) - private fun mathML(mst: MST) = MathMLSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst)) - - internal fun testLatex(mst: MST, expectedLatex: String) = assertEquals( - expected = expectedLatex, - actual = latex(mst), - ) - - internal fun testLatex(expression: String, expectedLatex: String) = assertEquals( - expected = expectedLatex, - actual = latex(expression.parseMath()), - ) - - internal fun testLatex(expression: MathSyntax, expectedLatex: String) = assertEquals( - expected = expectedLatex, - actual = LatexSyntaxRenderer.renderWithStringBuilder(expression), - ) - - internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", - actual = mathML(mst), - ) - - internal fun testMathML(expression: String, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", - actual = mathML(expression.parseMath()), - ) - - internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", - actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression), - ) -} diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 3a05c3d6d..70beab95a 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-7`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0-dev-6' + implementation 'space.kscience:kmath-complex:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -31,6 +31,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0-dev-6") + implementation("space.kscience:kmath-complex:0.3.0-dev-7") } ``` diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index 1c2e8a0a2..a28226d90 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -1,5 +1,3 @@ -import ru.mipt.npm.gradle.Maturity - /* * 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. @@ -21,7 +19,7 @@ kotlin.sourceSets { readme { description = "Complex numbers and quaternions." - maturity = Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-core/README.md b/kmath-core/README.md index b83fb13d0..e28873045 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-7`. **Gradle:** ```gradle @@ -26,7 +26,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0-dev-6' + implementation 'space.kscience:kmath-core:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -38,6 +38,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0-dev-6") + implementation("space.kscience:kmath-core:0.3.0-dev-7") } ``` diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index df70aa40b..f1a2ed40f 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -21,7 +19,7 @@ kotlin.sourceSets { readme { description = "Core classes, algebra definitions, basic linear algebra" - maturity = Maturity.DEVELOPMENT + maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt new file mode 100644 index 000000000..b5e652784 --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt @@ -0,0 +1,18 @@ +package space.kscience.kmath.expressions + +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test + +internal class InterpretTest { + @Test + fun interpretation() { + val expr = MstField { + val x = bindSymbol(Symbol.x) + x * 2.0 + number(2.0) / x - 16.0 + }.toExpression(DoubleField) + expr(Symbol.x to 2.2) + } +} diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index 30f9ce1f9..531bbd935 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -29,5 +27,5 @@ kotlin.sourceSets { } readme { - maturity = Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index cae11724d..3bf29f803 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-7`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0-dev-6' + implementation 'space.kscience:kmath-ejml:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0-dev-6") + implementation("space.kscience:kmath-ejml:0.3.0-dev-7") } ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 922e6572b..20e52deb2 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-7`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0-dev-6' + implementation 'space.kscience:kmath-for-real:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0-dev-6") + implementation("space.kscience:kmath-for-real:0.3.0-dev-7") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index eef677565..d5907f1c5 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-7`. **Gradle:** ```gradle @@ -22,7 +22,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0-dev-6' + implementation 'space.kscience:kmath-functions:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -34,6 +34,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0-dev-6") + implementation("space.kscience:kmath-functions:0.3.0-dev-7") } ``` diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index 65db43edf..121498ce8 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -17,5 +15,5 @@ kotlin.sourceSets.commonMain { } readme { - maturity = Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE } diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index 024e34076..af3ebaed9 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -28,5 +26,5 @@ kotlin.sourceSets { } readme { - maturity = Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE } diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index 66018a227..3ed73451d 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -10,6 +10,7 @@ import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.MstAlgebra import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals @@ -19,8 +20,8 @@ import kotlin.test.fail internal class AdaptingTests { @Test fun symbol() { - val c1 = MstAlgebra.bindSymbol("x") - assertTrue(c1.toSVar>().name == "x") + val c1 = MstAlgebra.bindSymbol(x.identity) + assertEquals(x.identity, c1.toSVar>().name) val c2 = "kitten".parseMath().toSFun>() if (c2 is SVar) assertTrue(c2.name == "kitten") else fail() } @@ -45,23 +46,27 @@ internal class AdaptingTests { @Test fun simpleFunctionDerivative() { - val x = MstAlgebra.bindSymbol("x").toSVar>() + val xSVar = MstAlgebra.bindSymbol(x.identity).toSVar>() val quadratic = "x^2-4*x-44".parseMath().toSFun>() - val actualDerivative = quadratic.d(x).toMst().compileToExpression(DoubleField) + val actualDerivative = quadratic.d(xSVar).toMst().compileToExpression(DoubleField) val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField) - assertEquals(actualDerivative("x" to 123.0), expectedDerivative("x" to 123.0)) + assertEquals(actualDerivative(x to 123.0), expectedDerivative(x to 123.0)) } @Test fun moreComplexDerivative() { - val x = MstAlgebra.bindSymbol("x").toSVar>() + val xSVar = MstAlgebra.bindSymbol(x.identity).toSVar>() val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun>() - val actualDerivative = composition.d(x).toMst().compileToExpression(DoubleField) + val actualDerivative = composition.d(xSVar).toMst().compileToExpression(DoubleField) - val expectedDerivative = - "-(2*x*cos(x^2)+2*sin(x)*cos(x)-16)/(2*sqrt(sin(x^2)-16*x-cos(x)^2))".parseMath().compileToExpression(DoubleField) + val expectedDerivative = "-(2*x*cos(x^2)+2*sin(x)*cos(x)-16)/(2*sqrt(sin(x^2)-16*x-cos(x)^2))" + .parseMath() + .compileToExpression(DoubleField) + assertEquals(actualDerivative(x to 0.1), expectedDerivative(x to 0.1)) + } - assertEquals(actualDerivative("x" to 0.1), expectedDerivative("x" to 0.1)) + private companion object { + private val x by symbol } } diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 829fe4142..66e0483a4 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-6`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-7`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0-dev-6' + implementation 'space.kscience:kmath-nd4j:0.3.0-dev-7' } ``` **Gradle Kotlin DSL:** @@ -32,7 +32,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0-dev-6") + implementation("space.kscience:kmath-nd4j:0.3.0-dev-7") } ``` diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index c7d891206..2b549f919 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") @@ -20,7 +18,7 @@ dependencies { readme { description = "ND4J NDStructure implementation and according NDAlgebra classes" - maturity = Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index dff504ef0..8522cf92f 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -30,5 +28,5 @@ kotlin.sourceSets { } readme { - maturity = Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 0d853dea7..747fe0252 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -3,8 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -import ru.mipt.npm.gradle.Maturity - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") @@ -18,5 +16,5 @@ dependencies { } readme { - maturity = Maturity.DEVELOPMENT + maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT } \ No newline at end of file From 0a0d0af94a4e586a0214815a272c17d7d530827b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 21 Apr 2021 19:46:02 +0700 Subject: [PATCH 232/393] Configure copyright scoping --- .gitignore | 1 + .idea/copyright/kmath.xml | 6 ++++++ .idea/copyright/profiles_settings.xml | 21 +++++++++++++++++++ .idea/scopes/Apply_copyright.xml | 4 ++++ benchmarks/build.gradle.kts | 5 ----- build.gradle.kts | 5 ----- examples/build.gradle.kts | 5 ----- .../kscience/kmath/functions/integrate.kt | 5 +++++ .../kmath/functions/matrixIntegration.kt | 5 +++++ gradlew | 15 +++++++++++-- kmath-ast/build.gradle.kts | 5 ----- .../kmath/ast/ParserPrecedenceTest.kt | 5 +++++ .../space/kscisnce/kmath/ast/ParserTest.kt | 5 +++++ .../internal/astring/astring.typealises.kt | 5 +++++ .../kscience/kmath/internal/base64/base64.kt | 5 +++++ .../kmath/internal/binaryen/index.binaryen.kt | 5 +++++ .../binaryen/index.binaryen.typealiases.kt | 5 +++++ .../kscience/kmath/internal/stream/stream.kt | 5 +++++ .../lib.dom.WebAssembly.module_dukat.kt | 5 +++++ .../nonDeclarations.WebAssembly.kt | 5 +++++ .../kmath/wasm/internal/WasmBuilder.kt | 5 +++++ .../wasm/internal/f64StandardFunctions.kt | 5 +++++ .../kotlin/space/kscience/kmath/wasm/wasm.kt | 5 +++++ .../kscience/kmath/ast/TestExecutionTime.kt | 5 +++++ .../kscience/kmath/wasm/TestWasmSpecific.kt | 5 +++++ kmath-commons/build.gradle.kts | 6 +----- kmath-complex/build.gradle.kts | 5 ----- kmath-core/build.gradle.kts | 5 ----- .../kmath/expressions/InterpretTest.kt | 5 +++++ kmath-coroutines/build.gradle.kts | 5 ----- kmath-functions/build.gradle.kts | 5 ----- kmath-geometry/build.gradle.kts | 5 ----- kmath-histograms/build.gradle.kts | 5 ----- kmath-kotlingrad/build.gradle.kts | 7 +------ kmath-memory/build.gradle.kts | 7 +------ kmath-nd4j/build.gradle.kts | 5 ----- kmath-stat/build.gradle.kts | 5 ----- kmath-viktor/build.gradle.kts | 5 ----- settings.gradle.kts | 5 ----- 39 files changed, 133 insertions(+), 89 deletions(-) create mode 100644 .idea/copyright/kmath.xml create mode 100644 .idea/copyright/profiles_settings.xml create mode 100644 .idea/scopes/Apply_copyright.xml diff --git a/.gitignore b/.gitignore index 2a13b9e3c..d6c4af4e3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ out/ .idea/ !.idea/copyright/ +!.idea/scopes/ .vscode/ diff --git a/.idea/copyright/kmath.xml b/.idea/copyright/kmath.xml new file mode 100644 index 000000000..17e44e4d0 --- /dev/null +++ b/.idea/copyright/kmath.xml @@ -0,0 +1,6 @@ + + + + diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 000000000..b538bdf41 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/scopes/Apply_copyright.xml b/.idea/scopes/Apply_copyright.xml new file mode 100644 index 000000000..0eb589133 --- /dev/null +++ b/.idea/scopes/Apply_copyright.xml @@ -0,0 +1,4 @@ + + + diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index d6796ed46..88f034a2a 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") kotlin("plugin.allopen") diff --git a/build.gradle.kts b/build.gradle.kts index a7c9144a7..4e0b6f256 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { id("ru.mipt.npm.gradle.project") } diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 67fe9853a..56feee9dc 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("jvm") } diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt index 90542adf4..6990e8c8f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt @@ -1,3 +1,8 @@ +/* + * 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.integration.integrate diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt index bd431c22c..8020df8f6 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt @@ -1,3 +1,8 @@ +/* + * 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.integration.integrate diff --git a/gradlew b/gradlew index 6ad9eb930..4f906e0c8 100755 --- a/gradlew +++ b/gradlew @@ -1,8 +1,19 @@ #!/usr/bin/env sh # -# 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. +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # ############################################################################## diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 15357b2d5..b4a0b28ac 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt index 509f87d98..14ceefc30 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt @@ -1,3 +1,8 @@ +/* + * 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.kscisnce.kmath.ast import space.kscience.kmath.ast.parseMath diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt index 13f5b3290..a0dcba9c0 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt @@ -1,3 +1,8 @@ +/* + * 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.kscisnce.kmath.ast import space.kscience.kmath.ast.parseMath diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt index 1f6a5f04d..93b4f6ce6 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt @@ -1,3 +1,8 @@ +/* + * 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.internal.astring internal typealias Generator = Any diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt index a0c7cb6ee..86e0cede7 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:Suppress( "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt index d3e3539c6..42b6ac7d8 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:Suppress( "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt index f89db20e2..523b13b40 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:Suppress("PackageDirectoryMismatch", "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "KDocMissingDocumentation") package space.kscience.kmath.internal.binaryen diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt index ae6c7eb35..52be5530f 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt @@ -1,3 +1,8 @@ +/* + * 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.internal.stream import space.kscience.kmath.internal.emitter.Emitter diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt index 322a2fa7b..3754c3eff 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:JsQualifier("WebAssembly") @file:Suppress( diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt index 095e46140..59733299a 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt @@ -1,3 +1,8 @@ +/* + * 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. + */ + @file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt index a031a4de4..bd2b340a0 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -1,3 +1,8 @@ +/* + * 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.wasm.internal import space.kscience.kmath.expressions.Expression diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt index cb0d71ad5..21a88b5d0 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt @@ -1,3 +1,8 @@ +/* + * 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.wasm.internal import space.kscience.kmath.internal.base64.toUint8Array diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt index 822dedc3a..d44c4e49d 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt @@ -1,3 +1,8 @@ +/* + * 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.wasm import space.kscience.kmath.estree.compileWith diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt index 634a89b26..01746ddb6 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt @@ -1,3 +1,8 @@ +/* + * 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.ast import space.kscience.kmath.expressions.* diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt index e627f551c..dd5452d04 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt @@ -1,3 +1,8 @@ +/* + * 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.wasm import space.kscience.kmath.expressions.MstExtendedField diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index 570ac2b74..a208c956c 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -1,12 +1,8 @@ -/* - * 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. - */ - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") } + description = "Commons math binding for kmath" dependencies { diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index a28226d90..ea74df646 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index f1a2ed40f..92a5f419d 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt index b5e652784..980819364 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt @@ -1,3 +1,8 @@ +/* + * 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.expressions import space.kscience.kmath.misc.Symbol diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index 531bbd935..1546e7d96 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index ca678bc0e..622b8f8da 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index 121498ce8..9b6e593b2 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index af3ebaed9..2167726c0 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index 576c073c3..f627beec9 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") @@ -16,4 +11,4 @@ dependencies { readme { maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE -} \ No newline at end of file +} diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 50c317324..288c61a51 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") @@ -14,4 +9,4 @@ readme { description = """ An API and basic implementation for arranging objects in a continous memory block. """.trimIndent() -} \ No newline at end of file +} diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 2b549f919..bc61060db 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index 8522cf92f..e8f629f7a 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("multiplatform") id("ru.mipt.npm.gradle.common") diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 747fe0252..232bd1388 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") diff --git a/settings.gradle.kts b/settings.gradle.kts index 553367a22..ca36168e1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,8 +1,3 @@ -/* - * 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. - */ - pluginManagement { repositories { mavenLocal() From cfa9077e29f16417878eb8ebca54ce973da19741 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 21 Apr 2021 19:50:33 +0700 Subject: [PATCH 233/393] Move AST rendering tests to common --- .../kmath/ast/rendering/TestFeatures.kt | 100 ++++++++++++++++++ .../kscisnce/kmath/ast/rendering/TestLatex.kt | 73 +++++++++++++ .../kmath/ast/rendering/TestMathML.kt | 92 ++++++++++++++++ .../kmath/ast/rendering/TestStages.kt | 33 ++++++ .../kscisnce/kmath/ast/rendering/TestUtils.kt | 46 ++++++++ 5 files changed, 344 insertions(+) create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt new file mode 100644 index 000000000..1584293ce --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt @@ -0,0 +1,100 @@ +/* + * 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.ast.rendering + +import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import space.kscience.kmath.expressions.MST.Numeric +import kotlin.test.Test + +internal class TestFeatures { + @Test + fun printSymbolic() = testLatex("x", "x") + + @Test + fun printNumeric() { + val num = object : Number() { + override fun toByte(): Byte = throw UnsupportedOperationException() + override fun toChar(): Char = throw UnsupportedOperationException() + override fun toDouble(): Double = throw UnsupportedOperationException() + override fun toFloat(): Float = throw UnsupportedOperationException() + override fun toInt(): Int = throw UnsupportedOperationException() + override fun toLong(): Long = throw UnsupportedOperationException() + override fun toShort(): Short = throw UnsupportedOperationException() + override fun toString(): String = "foo" + } + + testLatex(Numeric(num), "foo") + } + + @Test + fun prettyPrintFloats() { + testLatex(Numeric(Double.NaN), "NaN") + testLatex(Numeric(Double.POSITIVE_INFINITY), "\\infty") + testLatex(Numeric(Double.NEGATIVE_INFINITY), "-\\infty") + testLatex(Numeric(1.0), "1") + testLatex(Numeric(-1.0), "-1") + testLatex(Numeric(1.42), "1.42") + testLatex(Numeric(-1.42), "-1.42") + testLatex(Numeric(1.1e10), "1.1\\times10^{10}") + testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}") + testLatex(Numeric(-1.1e-10), "-1.1\\times10^{-10}") + testLatex(Numeric(-1.1e10), "-1.1\\times10^{10}") + } + + @Test + fun prettyPrintIntegers() { + testLatex(Numeric(42), "42") + testLatex(Numeric(-42), "-42") + } + + @Test + fun prettyPrintPi() { + testLatex("pi", "\\pi") + } + + @Test + fun binaryPlus() = testLatex("2+2", "2+2") + + @Test + fun binaryMinus() = testLatex("2-2", "2-2") + + @Test + fun fraction() = testLatex("2/2", "\\frac{2}{2}") + + @Test + fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)") + + @Test + fun unaryOperator() = testLatex("f(x)", "\\operatorname{f}\\,\\left(x\\right)") + + @Test + fun power() = testLatex("x^y", "x^{y}") + + @Test + fun squareRoot() = testLatex("sqrt(x)", "\\sqrt{x}") + + @Test + fun exponential() = testLatex("exp(x)", "e^{x}") + + @Test + fun multiplication() = testLatex("x*1", "x\\times1") + + @Test + fun inverseTrigonometry() { + testLatex("asin(x)", "\\operatorname{sin}^{-1}\\,\\left(x\\right)") + testLatex("asinh(x)", "\\operatorname{sinh}^{-1}\\,\\left(x\\right)") + testLatex("acos(x)", "\\operatorname{cos}^{-1}\\,\\left(x\\right)") + testLatex("acosh(x)", "\\operatorname{cosh}^{-1}\\,\\left(x\\right)") + testLatex("atan(x)", "\\operatorname{tan}^{-1}\\,\\left(x\\right)") + testLatex("atanh(x)", "\\operatorname{tanh}^{-1}\\,\\left(x\\right)") + } + +// @Test +// fun unaryPlus() { +// testLatex("+1", "+1") +// testLatex("+1", "++1") +// } +} diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt new file mode 100644 index 000000000..6322df25d --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt @@ -0,0 +1,73 @@ +/* + * 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.ast.rendering + +import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.operations.GroupOperations +import kotlin.test.Test + +internal class TestLatex { + @Test + fun number() = testLatex("42", "42") + + @Test + fun symbol() = testLatex("x", "x") + + @Test + fun operatorName() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") + + @Test + fun specialSymbol() { + testLatex(MST.Numeric(Double.POSITIVE_INFINITY), "\\infty") + testLatex("pi", "\\pi") + } + + @Test + fun operand() { + testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") + testLatex("1+1", "1+1") + } + + @Test + fun unaryOperator() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)") + + @Test + fun unaryPlus() = testLatex(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1") + + @Test + fun unaryMinus() = testLatex("-x", "-x") + + @Test + fun radical() = testLatex("sqrt(x)", "\\sqrt{x}") + + @Test + fun superscript() = testLatex("x^y", "x^{y}") + + @Test + fun subscript() = testLatex(SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), "x_{123}") + + @Test + fun binaryOperator() = testLatex("f(x, y)", "\\operatorname{f}\\left(x,y\\right)") + + @Test + fun binaryPlus() = testLatex("x+x", "x+x") + + @Test + fun binaryMinus() = testLatex("x-x", "x-x") + + @Test + fun fraction() = testLatex("x/x", "\\frac{x}{x}") + + @Test + fun radicalWithIndex() = testLatex(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), "\\sqrt[x]{y}") + + @Test + fun multiplication() { + testLatex("x*1", "x\\times1") + testLatex("1*x", "1\\,x") + } +} diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt new file mode 100644 index 000000000..2d7bfad19 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt @@ -0,0 +1,92 @@ +/* + * 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.ast.rendering + +import space.kscience.kmath.ast.rendering.TestUtils.testMathML +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.operations.GroupOperations +import kotlin.test.Test + +internal class TestMathML { + @Test + fun number() = testMathML("42", "42") + + @Test + fun symbol() = testMathML("x", "x") + + @Test + fun operatorName() = testMathML( + "sin(1)", + "sin1", + ) + + @Test + fun specialSymbol() { + testMathML(MST.Numeric(Double.POSITIVE_INFINITY), "") + testMathML("pi", "π") + } + + @Test + fun operand() { + testMathML( + "sin(1)", + "sin1", + ) + + testMathML("1+1", "1+1") + } + + @Test + fun unaryOperator() = testMathML( + "sin(1)", + "sin1", + ) + + @Test + fun unaryPlus() = + testMathML(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1") + + @Test + fun unaryMinus() = testMathML("-x", "-x") + + @Test + fun radical() = testMathML("sqrt(x)", "x") + + @Test + fun superscript() = testMathML("x^y", "xy") + + @Test + fun subscript() = testMathML( + SubscriptSyntax("", SymbolSyntax("x"), NumberSyntax("123")), + "x123", + ) + + @Test + fun binaryOperator() = testMathML( + "f(x, y)", + "fx,y", + ) + + @Test + fun binaryPlus() = testMathML("x+x", "x+x") + + @Test + fun binaryMinus() = testMathML("x-x", "x-x") + + @Test + fun fraction() = testMathML("x/x", "xx") + + @Test + fun radicalWithIndex() = + testMathML(RadicalWithIndexSyntax("", SymbolSyntax("x"), SymbolSyntax("y")), + "yx") + + @Test + fun multiplication() { + testMathML("x*1", "x×1") + testMathML("1*x", "1x") + } +} diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt new file mode 100644 index 000000000..a4017fdb4 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt @@ -0,0 +1,33 @@ +/* + * 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.ast.rendering + +import space.kscience.kmath.ast.rendering.TestUtils.testLatex +import kotlin.test.Test + +internal class TestStages { + @Test + fun betterMultiplication() { + testLatex("a*1", "a\\times1") + testLatex("1*(2/3)", "1\\times\\left(\\frac{2}{3}\\right)") + testLatex("1*1", "1\\times1") + testLatex("2e10", "2\\times10^{10}") + testLatex("2*x", "2\\,x") + testLatex("2*(x+1)", "2\\,\\left(x+1\\right)") + testLatex("x*y", "x\\,y") + } + + @Test + fun parentheses() { + testLatex("(x+1)", "x+1") + testLatex("x*x*x", "x\\,x\\,x") + testLatex("(x+x)*x", "\\left(x+x\\right)\\,x") + testLatex("x+x*x", "x+x\\,x") + testLatex("x+x^x*x+x", "x+x^{x}\\,x+x") + testLatex("(x+x)^x+x*x", "\\left(x+x\\right)^{x}+x\\,x") + testLatex("x^(x+x)", "x^{x+x}") + } +} diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt new file mode 100644 index 000000000..7c9400532 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt @@ -0,0 +1,46 @@ +/* + * 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.ast.rendering + +import space.kscience.kmath.ast.parseMath +import space.kscience.kmath.expressions.MST +import kotlin.test.assertEquals + +internal object TestUtils { + private fun mathSyntax(mst: MST) = FeaturedMathRendererWithPostProcess.Default.render(mst) + private fun latex(mst: MST) = LatexSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst)) + private fun mathML(mst: MST) = MathMLSyntaxRenderer.renderWithStringBuilder(mathSyntax(mst)) + + internal fun testLatex(mst: MST, expectedLatex: String) = assertEquals( + expected = expectedLatex, + actual = latex(mst), + ) + + internal fun testLatex(expression: String, expectedLatex: String) = assertEquals( + expected = expectedLatex, + actual = latex(expression.parseMath()), + ) + + internal fun testLatex(expression: MathSyntax, expectedLatex: String) = assertEquals( + expected = expectedLatex, + actual = LatexSyntaxRenderer.renderWithStringBuilder(expression), + ) + + internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals( + expected = "$expectedMathML", + actual = mathML(mst), + ) + + internal fun testMathML(expression: String, expectedMathML: String) = assertEquals( + expected = "$expectedMathML", + actual = mathML(expression.parseMath()), + ) + + internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals( + expected = "$expectedMathML", + actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression), + ) +} From 488f5f00087ba45ea137a1ee527468cf4dd40dbc Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 8 Apr 2021 00:52:27 +0700 Subject: [PATCH 234/393] Redesign exponential function rendering --- .../ast/rendering/LatexSyntaxRenderer.kt | 9 + .../ast/rendering/MathMLSyntaxRenderer.kt | 13 + .../kmath/ast/rendering/MathRenderer.kt | 3 +- .../kmath/ast/rendering/MathSyntax.kt | 18 ++ .../kscience/kmath/ast/rendering/features.kt | 24 +- .../ast/rendering/multiplatformToString.kt | 9 + .../kscience/kmath/ast/rendering/stages.kt | 293 ++++++++++-------- .../kmath/ast/ParserPrecedenceTest.kt | 2 +- .../kmath/ast/ParserTest.kt | 3 +- .../kmath/ast/rendering/TestFeatures.kt | 16 + .../kmath/ast/rendering/TestLatex.kt | 0 .../kmath/ast/rendering/TestMathML.kt | 0 .../kmath/ast/rendering/TestStages.kt | 7 + .../kmath/ast/rendering/TestUtils.kt | 0 .../ast/rendering/multiplatformToString.kt | 18 ++ .../ast/rendering/multiplatformToString.kt | 9 + 16 files changed, 283 insertions(+), 141 deletions(-) create mode 100644 kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/ParserPrecedenceTest.kt (97%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/ParserTest.kt (95%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestFeatures.kt (81%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestLatex.kt (100%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestMathML.kt (100%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestStages.kt (81%) rename kmath-ast/src/commonTest/kotlin/space/{kscisnce => kscience}/kmath/ast/rendering/TestUtils.kt (100%) create mode 100644 kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt create mode 100644 kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt index 34230f3c8..1c82bd6e7 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -71,6 +71,15 @@ public object LatexSyntaxRenderer : SyntaxRenderer { append('}') } + is ExponentSyntax -> if (node.useOperatorForm) { + append("\\operatorname{exp}\\,") + render(node.operand) + } else { + append("e^{") + render(node.operand) + append('}') + } + is SuperscriptSyntax -> { render(node.left) append("^{") diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index f7487a356..decd4ba46 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -82,6 +82,19 @@ public object MathMLSyntaxRenderer : SyntaxRenderer { is RadicalSyntax -> tag("msqrt") { render(node.operand) } + is ExponentSyntax -> if (node.useOperatorForm) { + tag("mo") { append("exp") } + tag("mspace", "width" to "0.167em") + render(node.operand) + } else { + tag("msup") { + tag("mrow") { + tag("mi") { append("e") } + } + tag("mrow") { render(node.operand) } + } + } + is SuperscriptSyntax -> tag("msup") { tag("mrow") { render(node.left) } tag("mrow") { render(node.right) } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index 891e8f05b..9df2c54dd 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -83,7 +83,7 @@ public open class FeaturedMathRendererWithPostProcess( Fraction.Default, Power.Default, SquareRoot.Default, - Exponential.Default, + Exponent.Default, InverseTrigonometricOperations.Default, // Fallback option for unknown operations - printing them as operator @@ -100,6 +100,7 @@ public open class FeaturedMathRendererWithPostProcess( PrintSymbolic, ), listOf( + BetterExponent, SimplifyParentheses.Default, BetterMultiplication, ), diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt index 069e56c71..6a46bf535 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -189,6 +189,24 @@ public data class RadicalSyntax( } } +/** + * Represents exponential function. + * + * @property operand The argument of function. + * @property useOperatorForm `true` if operator form is used (*exp (x)*), `false` if exponentiation form is used + * (*ex*). + * @author Iaroslav Postovalov + */ +public data class ExponentSyntax( + public override val operation: String, + public override val operand: OperandSyntax, + public var useOperatorForm: Boolean, +) : UnarySyntax() { + init { + operand.parent = this + } +} + /** * Represents a syntax node with superscript (usually, for exponentiation). * diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index 5d6c7bb0a..c09282bb6 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -56,10 +56,14 @@ private fun printSignedNumberString(s: String): MathSyntax { public class PrettyPrintFloats(public val types: Set>) : RenderFeature { public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { if (node !is MST.Numeric || node.value::class !in types) return null - val toString = node.value.toString().removeSuffix(".0") + val toString = when (val v = node.value) { + is Float -> v.multiplatformToString() + is Double -> v.multiplatformToString() + else -> v.toString() + }.removeSuffix(".0") - if ('E' in toString) { - val (beforeE, afterE) = toString.split('E') + if (toString.contains('E', ignoreCase = true)) { + val (beforeE, afterE) = toString.split('E', ignoreCase = true) val significand = beforeE.toDouble().toString().removeSuffix(".0") val exponent = afterE.toDouble().toString().removeSuffix(".0") @@ -108,9 +112,7 @@ public class PrettyPrintFloats(public val types: Set>) : Rend */ public class PrettyPrintIntegers(public val types: Set>) : RenderFeature { public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Numeric || node.value::class !in types) - return null - + if (node !is MST.Numeric || node.value::class !in types) return null return printSignedNumberString(node.value.toString()) } @@ -282,15 +284,15 @@ public class SquareRoot(operations: Collection?) : Unary(operations) { } } -public class Exponential(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = SuperscriptSyntax( +public class Exponent(operations: Collection?) : Unary(operations) { + public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax( operation = node.operation, - left = SymbolSyntax(string = "e"), - right = parent.render(node.value), + operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), + useOperatorForm = true, ) public companion object { - public val Default: Exponential = Exponential(setOf(ExponentialOperations.EXP_OPERATION)) + public val Default: Exponent = Exponent(setOf(ExponentialOperations.EXP_OPERATION)) } } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt new file mode 100644 index 000000000..291399cee --- /dev/null +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -0,0 +1,9 @@ +/* + * 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.ast.rendering + +internal expect fun Double.multiplatformToString(): String +internal expect fun Float.multiplatformToString(): String diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt index 0ebb41b28..a08f089f1 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt @@ -16,69 +16,110 @@ import space.kscience.kmath.operations.RingOperations * @author Iaroslav Postovalov */ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage { - public override fun perform(node: MathSyntax) { - when (node) { - is NumberSyntax -> Unit - is SymbolSyntax -> Unit - is OperatorNameSyntax -> Unit - is SpecialSymbolSyntax -> Unit - is OperandSyntax -> perform(node.operand) + public override fun perform(node: MathSyntax): Unit = when (node) { + is NumberSyntax -> Unit + is SymbolSyntax -> Unit + is OperatorNameSyntax -> Unit + is SpecialSymbolSyntax -> Unit + is OperandSyntax -> perform(node.operand) - is UnaryOperatorSyntax -> { - perform(node.prefix) - perform(node.operand) - } - - is UnaryPlusSyntax -> perform(node.operand) - is UnaryMinusSyntax -> perform(node.operand) - is RadicalSyntax -> perform(node.operand) - - is SuperscriptSyntax -> { - perform(node.left) - perform(node.right) - } - - is SubscriptSyntax -> { - perform(node.left) - perform(node.right) - } - - is BinaryOperatorSyntax -> { - perform(node.prefix) - perform(node.left) - perform(node.right) - } - - is BinaryPlusSyntax -> { - perform(node.left) - perform(node.right) - } - - is BinaryMinusSyntax -> { - perform(node.left) - perform(node.right) - } - - is FractionSyntax -> { - perform(node.left) - perform(node.right) - } - - is RadicalWithIndexSyntax -> { - perform(node.left) - perform(node.right) - } - - is MultiplicationSyntax -> { - node.times = node.right.operand is NumberSyntax && !node.right.parentheses - || node.left.operand is NumberSyntax && node.right.operand is FractionSyntax - || node.left.operand is NumberSyntax && node.right.operand is NumberSyntax - || node.left.operand is NumberSyntax && node.right.operand is SuperscriptSyntax && node.right.operand.left is NumberSyntax - - perform(node.left) - perform(node.right) - } + is UnaryOperatorSyntax -> { + perform(node.prefix) + perform(node.operand) } + + is UnaryPlusSyntax -> perform(node.operand) + is UnaryMinusSyntax -> perform(node.operand) + is RadicalSyntax -> perform(node.operand) + is ExponentSyntax -> perform(node.operand) + + is SuperscriptSyntax -> { + perform(node.left) + perform(node.right) + } + + is SubscriptSyntax -> { + perform(node.left) + perform(node.right) + } + + is BinaryOperatorSyntax -> { + perform(node.prefix) + perform(node.left) + perform(node.right) + } + + is BinaryPlusSyntax -> { + perform(node.left) + perform(node.right) + } + + is BinaryMinusSyntax -> { + perform(node.left) + perform(node.right) + } + + is FractionSyntax -> { + perform(node.left) + perform(node.right) + } + + is RadicalWithIndexSyntax -> { + perform(node.left) + perform(node.right) + } + + is MultiplicationSyntax -> { + node.times = node.right.operand is NumberSyntax && !node.right.parentheses + || node.left.operand is NumberSyntax && node.right.operand is FractionSyntax + || node.left.operand is NumberSyntax && node.right.operand is NumberSyntax + || node.left.operand is NumberSyntax && node.right.operand is SuperscriptSyntax && node.right.operand.left is NumberSyntax + + perform(node.left) + perform(node.right) + } + } +} + + +/** + * Applies [ExponentSyntax.useOperatorForm] to [ExponentSyntax] when the operand contains a fraction, a + * superscript or a subscript to improve readability. + * + * @author Iaroslav Postovalov + */ +public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage { + private fun perform0(node: MathSyntax): Boolean { + return when (node) { + is NumberSyntax -> false + is SymbolSyntax -> false + is OperatorNameSyntax -> false + is SpecialSymbolSyntax -> false + is OperandSyntax -> perform0(node.operand) + is UnaryOperatorSyntax -> perform0(node.prefix) || perform0(node.operand) + is UnaryPlusSyntax -> perform0(node.operand) + is UnaryMinusSyntax -> perform0(node.operand) + is RadicalSyntax -> perform0(node.operand) + + is ExponentSyntax -> { + val r = perform0(node.operand) + node.useOperatorForm = r + r + } + + is SuperscriptSyntax -> true + is SubscriptSyntax -> true + is BinaryOperatorSyntax -> perform0(node.prefix) || perform0(node.left) || perform0(node.right) + is BinaryPlusSyntax -> perform0(node.left) || perform0(node.right) + is BinaryMinusSyntax -> perform0(node.left) || perform0(node.right) + is FractionSyntax -> true + is RadicalWithIndexSyntax -> perform0(node.left) || perform0(node.right) + is MultiplicationSyntax -> perform0(node.left) || perform0(node.right) + } + } + + public override fun perform(node: MathSyntax) { + perform0(node) } } @@ -90,89 +131,89 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro */ public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) : FeaturedMathRendererWithPostProcess.PostProcessStage { - public override fun perform(node: MathSyntax) { - when (node) { - is NumberSyntax -> Unit - is SymbolSyntax -> Unit - is OperatorNameSyntax -> Unit - is SpecialSymbolSyntax -> Unit + public override fun perform(node: MathSyntax): Unit = when (node) { + is NumberSyntax -> Unit + is SymbolSyntax -> Unit + is OperatorNameSyntax -> Unit + is SpecialSymbolSyntax -> Unit - is OperandSyntax -> { - val isRightOfSuperscript = - (node.parent is SuperscriptSyntax) && (node.parent as SuperscriptSyntax).right === node + is OperandSyntax -> { + val isRightOfSuperscript = + (node.parent is SuperscriptSyntax) && (node.parent as SuperscriptSyntax).right === node - val precedence = precedenceFunction(node.operand) + val precedence = precedenceFunction(node.operand) - val needParenthesesByPrecedence = when (val parent = node.parent) { - null -> false + val needParenthesesByPrecedence = when (val parent = node.parent) { + null -> false - is BinarySyntax -> { - val parentPrecedence = precedenceFunction(parent) + is BinarySyntax -> { + val parentPrecedence = precedenceFunction(parent) - parentPrecedence < precedence || - parentPrecedence == precedence && parentPrecedence != 0 && node === parent.right - } - - else -> precedence > precedenceFunction(parent) + parentPrecedence < precedence || + parentPrecedence == precedence && parentPrecedence != 0 && node === parent.right } - node.parentheses = !isRightOfSuperscript - && (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax) - - perform(node.operand) + else -> precedence > precedenceFunction(parent) } - is UnaryOperatorSyntax -> { - perform(node.prefix) - perform(node.operand) - } + val isInsideExpOperator = + node.parent is ExponentSyntax && (node.parent as ExponentSyntax).useOperatorForm - is UnaryPlusSyntax -> perform(node.operand) - is UnaryMinusSyntax -> { - perform(node.operand) - } - is RadicalSyntax -> perform(node.operand) + node.parentheses = !isRightOfSuperscript + && (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax || isInsideExpOperator) - is SuperscriptSyntax -> { - perform(node.left) - perform(node.right) - } + perform(node.operand) + } - is SubscriptSyntax -> { - perform(node.left) - perform(node.right) - } + is UnaryOperatorSyntax -> { + perform(node.prefix) + perform(node.operand) + } - is BinaryOperatorSyntax -> { - perform(node.prefix) - perform(node.left) - perform(node.right) - } + is UnaryPlusSyntax -> perform(node.operand) + is UnaryMinusSyntax -> perform(node.operand) + is RadicalSyntax -> perform(node.operand) + is ExponentSyntax -> perform(node.operand) - is BinaryPlusSyntax -> { - perform(node.left) - perform(node.right) - } + is SuperscriptSyntax -> { + perform(node.left) + perform(node.right) + } - is BinaryMinusSyntax -> { - perform(node.left) - perform(node.right) - } + is SubscriptSyntax -> { + perform(node.left) + perform(node.right) + } - is FractionSyntax -> { - perform(node.left) - perform(node.right) - } + is BinaryOperatorSyntax -> { + perform(node.prefix) + perform(node.left) + perform(node.right) + } - is MultiplicationSyntax -> { - perform(node.left) - perform(node.right) - } + is BinaryPlusSyntax -> { + perform(node.left) + perform(node.right) + } - is RadicalWithIndexSyntax -> { - perform(node.left) - perform(node.right) - } + is BinaryMinusSyntax -> { + perform(node.left) + perform(node.right) + } + + is FractionSyntax -> { + perform(node.left) + perform(node.right) + } + + is MultiplicationSyntax -> { + perform(node.left) + perform(node.right) + } + + is RadicalWithIndexSyntax -> { + perform(node.left) + perform(node.right) } } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt similarity index 97% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt index 14ceefc30..ca3a95bc8 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt @@ -3,7 +3,7 @@ * 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.kscisnce.kmath.ast +package space.kscience.kmath.ast import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.evaluate diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt similarity index 95% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt index a0dcba9c0..185659a1f 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt @@ -3,9 +3,8 @@ * 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.kscisnce.kmath.ast +package space.kscience.kmath.ast -import space.kscience.kmath.ast.parseMath import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.ComplexField import space.kscience.kmath.expressions.evaluate diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt similarity index 81% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt index 1584293ce..1ab20ed85 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestFeatures.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt @@ -42,6 +42,22 @@ internal class TestFeatures { testLatex(Numeric(1.1e-10), "1.1\\times10^{-10}") testLatex(Numeric(-1.1e-10), "-1.1\\times10^{-10}") testLatex(Numeric(-1.1e10), "-1.1\\times10^{10}") + testLatex(Numeric(0.001), "0.001") + testLatex(Numeric(0.0000001), "1\\times10^{-7}") + + testLatex(Numeric(Float.NaN), "NaN") + testLatex(Numeric(Float.POSITIVE_INFINITY), "\\infty") + testLatex(Numeric(Float.NEGATIVE_INFINITY), "-\\infty") + testLatex(Numeric(1.0f), "1") + testLatex(Numeric(-1.0f), "-1") + testLatex(Numeric(1.42f), "1.42") + testLatex(Numeric(-1.42f), "-1.42") + testLatex(Numeric(1e10f), "1\\times10^{10}") + testLatex(Numeric(1e-10f), "1\\times10^{-10}") + testLatex(Numeric(-1e-10f), "-1\\times10^{-10}") + testLatex(Numeric(-1e10f), "-1\\times10^{10}") + testLatex(Numeric(0.001f), "0.001") + testLatex(Numeric(0.0000001f), "1\\times10^{-7}") } @Test diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt similarity index 100% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestLatex.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt similarity index 100% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestMathML.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt similarity index 81% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt index a4017fdb4..599e43eb2 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestStages.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt @@ -30,4 +30,11 @@ internal class TestStages { testLatex("(x+x)^x+x*x", "\\left(x+x\\right)^{x}+x\\,x") testLatex("x^(x+x)", "x^{x+x}") } + + @Test + fun exponent() { + testLatex("exp(x)", "e^{x}") + testLatex("exp(x/2)", "\\operatorname{exp}\\,\\left(\\frac{x}{2}\\right)") + testLatex("exp(x^2)", "\\operatorname{exp}\\,\\left(x^{2}\\right)") + } } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt similarity index 100% rename from kmath-ast/src/commonTest/kotlin/space/kscisnce/kmath/ast/rendering/TestUtils.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt new file mode 100644 index 000000000..521907d2c --- /dev/null +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -0,0 +1,18 @@ +/* + * 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.ast.rendering + +internal actual fun Double.multiplatformToString(): String { + val d = this + if (d >= 1e7 || d <= -1e7) return js("d.toExponential()") as String + return toString() +} + +internal actual fun Float.multiplatformToString(): String { + val d = this + if (d >= 1e7f || d <= -1e7f) return js("d.toExponential()") as String + return toString() +} diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt new file mode 100644 index 000000000..556adbe7d --- /dev/null +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -0,0 +1,9 @@ +/* + * 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.ast.rendering + +internal actual fun Double.multiplatformToString(): String = toString() +internal actual fun Float.multiplatformToString(): String = toString() From cc11df617489c6d3d8105b72cf5a472af1c90c01 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 21 Apr 2021 19:51:34 +0100 Subject: [PATCH 235/393] Casting receiver --- .../kmath/tensors/AnalyticTensorAlgebra.kt | 38 +-- .../kmath/tensors/LinearOpsTensorAlgebra.kt | 21 +- .../kscience/kmath/tensors/TensorAlgebra.kt | 50 ++-- .../tensors/TensorPartialDivisionAlgebra.kt | 12 +- .../core/BroadcastDoubleTensorAlgebra.kt | 57 ++-- .../kmath/tensors/core/BufferedTensor.kt | 48 ++- .../core/DoubleAnalyticTensorAlgebra.kt | 37 +-- .../core/DoubleLinearOpsTensorAlgebra.kt | 65 ++-- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 279 +++++++++--------- .../kscience/kmath/tensors/core/checks.kt | 41 +-- .../kscience/kmath/tensors/core/linutils.kt | 4 +- .../kscience/kmath/tensors/core/utils.kt | 4 +- 12 files changed, 326 insertions(+), 330 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt index fa1de81fa..2a8b228f4 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt @@ -1,58 +1,58 @@ package space.kscience.kmath.tensors -public interface AnalyticTensorAlgebra> : - TensorPartialDivisionAlgebra { +public interface AnalyticTensorAlgebra : + TensorPartialDivisionAlgebra { //https://pytorch.org/docs/stable/generated/torch.exp.html - public fun TensorType.exp(): TensorType + public fun TensorStructure.exp(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.log.html - public fun TensorType.log(): TensorType + public fun TensorStructure.log(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.sqrt.html - public fun TensorType.sqrt(): TensorType + public fun TensorStructure.sqrt(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos - public fun TensorType.cos(): TensorType + public fun TensorStructure.cos(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.acos - public fun TensorType.acos(): TensorType + public fun TensorStructure.acos(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.cosh - public fun TensorType.cosh(): TensorType + public fun TensorStructure.cosh(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.acosh - public fun TensorType.acosh(): TensorType + public fun TensorStructure.acosh(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sin - public fun TensorType.sin(): TensorType + public fun TensorStructure.sin(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asin - public fun TensorType.asin(): TensorType + public fun TensorStructure.asin(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sinh - public fun TensorType.sinh(): TensorType + public fun TensorStructure.sinh(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asinh - public fun TensorType.asinh(): TensorType + public fun TensorStructure.asinh(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.tan - public fun TensorType.tan(): TensorType + public fun TensorStructure.tan(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.atan - public fun TensorType.atan(): TensorType + public fun TensorStructure.atan(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.tanh - public fun TensorType.tanh(): TensorType + public fun TensorStructure.tanh(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.atanh - public fun TensorType.atanh(): TensorType + public fun TensorStructure.atanh(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.ceil.html#torch.ceil - public fun TensorType.ceil(): TensorType + public fun TensorStructure.ceil(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor - public fun TensorType.floor(): TensorType + public fun TensorStructure.floor(): TensorStructure } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt index 87c459f35..8ca8945a5 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt @@ -1,31 +1,32 @@ package space.kscience.kmath.tensors -public interface LinearOpsTensorAlgebra, IndexTensorType : TensorStructure> : - TensorPartialDivisionAlgebra { +public interface LinearOpsTensorAlgebra : + TensorPartialDivisionAlgebra { //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det - public fun TensorType.det(): TensorType + public fun TensorStructure.det(): TensorStructure //https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv - public fun TensorType.inv(): TensorType + public fun TensorStructure.inv(): TensorStructure //https://pytorch.org/docs/stable/linalg.html#torch.linalg.cholesky - public fun TensorType.cholesky(): TensorType + public fun TensorStructure.cholesky(): TensorStructure //https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr - public fun TensorType.qr(): Pair + public fun TensorStructure.qr(): Pair, TensorStructure> //https://pytorch.org/docs/stable/generated/torch.lu.html - public fun TensorType.lu(): Pair + public fun TensorStructure.lu(): Pair, TensorStructure> //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html - public fun luPivot(luTensor: TensorType, pivotsTensor: IndexTensorType): Triple + public fun luPivot(luTensor: TensorStructure, pivotsTensor: TensorStructure): + Triple, TensorStructure, TensorStructure> //https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd - public fun TensorType.svd(): Triple + public fun TensorStructure.svd(): Triple, TensorStructure, TensorStructure> //https://pytorch.org/docs/stable/generated/torch.symeig.html - public fun TensorType.symEig(): Pair + public fun TensorStructure.symEig(): Pair, TensorStructure> } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt index 8fd1cf2ed..f64d49dd8 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt @@ -1,46 +1,46 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Algebra_over_Ring -public interface TensorAlgebra> { +public interface TensorAlgebra { - public fun TensorType.value(): T + public fun TensorStructure.value(): T - public operator fun T.plus(other: TensorType): TensorType - public operator fun TensorType.plus(value: T): TensorType - public operator fun TensorType.plus(other: TensorType): TensorType - public operator fun TensorType.plusAssign(value: T): Unit - public operator fun TensorType.plusAssign(other: TensorType): Unit + public operator fun T.plus(other: TensorStructure): TensorStructure + public operator fun TensorStructure.plus(value: T): TensorStructure + public operator fun TensorStructure.plus(other: TensorStructure): TensorStructure + public operator fun TensorStructure.plusAssign(value: T): Unit + public operator fun TensorStructure.plusAssign(other: TensorStructure): Unit - public operator fun T.minus(other: TensorType): TensorType - public operator fun TensorType.minus(value: T): TensorType - public operator fun TensorType.minus(other: TensorType): TensorType - public operator fun TensorType.minusAssign(value: T): Unit - public operator fun TensorType.minusAssign(other: TensorType): Unit + public operator fun T.minus(other: TensorStructure): TensorStructure + public operator fun TensorStructure.minus(value: T): TensorStructure + public operator fun TensorStructure.minus(other: TensorStructure): TensorStructure + public operator fun TensorStructure.minusAssign(value: T): Unit + public operator fun TensorStructure.minusAssign(other: TensorStructure): Unit - public operator fun T.times(other: TensorType): TensorType - public operator fun TensorType.times(value: T): TensorType - public operator fun TensorType.times(other: TensorType): TensorType - public operator fun TensorType.timesAssign(value: T): Unit - public operator fun TensorType.timesAssign(other: TensorType): Unit - public operator fun TensorType.unaryMinus(): TensorType + public operator fun T.times(other: TensorStructure): TensorStructure + public operator fun TensorStructure.times(value: T): TensorStructure + public operator fun TensorStructure.times(other: TensorStructure): TensorStructure + public operator fun TensorStructure.timesAssign(value: T): Unit + public operator fun TensorStructure.timesAssign(other: TensorStructure): Unit + public operator fun TensorStructure.unaryMinus(): TensorStructure //https://pytorch.org/cppdocs/notes/tensor_indexing.html - public operator fun TensorType.get(i: Int): TensorType + public operator fun TensorStructure.get(i: Int): TensorStructure //https://pytorch.org/docs/stable/generated/torch.transpose.html - public fun TensorType.transpose(i: Int = -2, j: Int = -1): TensorType + public fun TensorStructure.transpose(i: Int = -2, j: Int = -1): TensorStructure //https://pytorch.org/docs/stable/tensor_view.html - public fun TensorType.view(shape: IntArray): TensorType - public fun TensorType.viewAs(other: TensorType): TensorType + public fun TensorStructure.view(shape: IntArray): TensorStructure + public fun TensorStructure.viewAs(other: TensorStructure): TensorStructure //https://pytorch.org/docs/stable/generated/torch.matmul.html - public infix fun TensorType.dot(other: TensorType): TensorType + public infix fun TensorStructure.dot(other: TensorStructure): TensorStructure //https://pytorch.org/docs/stable/generated/torch.diag_embed.html public fun diagonalEmbedding( - diagonalEntries: TensorType, + diagonalEntries: TensorStructure, offset: Int = 0, dim1: Int = -2, dim2: Int = -1 - ): TensorType + ): TensorStructure } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt index 0b9079967..b37ac6b6e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt @@ -1,10 +1,10 @@ package space.kscience.kmath.tensors // https://proofwiki.org/wiki/Definition:Division_Algebra -public interface TensorPartialDivisionAlgebra> : - TensorAlgebra { - public operator fun TensorType.div(value: T): TensorType - public operator fun TensorType.div(other: TensorType): TensorType - public operator fun TensorType.divAssign(value: T) - public operator fun TensorType.divAssign(other: TensorType) +public interface TensorPartialDivisionAlgebra : + TensorAlgebra { + public operator fun TensorStructure.div(value: T): TensorStructure + public operator fun TensorStructure.div(other: TensorStructure): TensorStructure + public operator fun TensorStructure.divAssign(value: T) + public operator fun TensorStructure.divAssign(other: TensorStructure) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index f315f6b51..53c385197 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -1,11 +1,12 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.tensors.TensorStructure import kotlin.math.max public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { - override fun DoubleTensor.plus(other: DoubleTensor): DoubleTensor { - val broadcast = broadcastTensors(this, other) + override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> @@ -14,16 +15,16 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun DoubleTensor.plusAssign(other: DoubleTensor) { - val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] += - newOther.buffer.array()[this.bufferStart + i] + override fun TensorStructure.plusAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] += + newOther.buffer.array()[tensor.bufferStart + i] } } - override fun DoubleTensor.minus(other: DoubleTensor): DoubleTensor { - val broadcast = broadcastTensors(this, other) + override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> @@ -32,16 +33,16 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun DoubleTensor.minusAssign(other: DoubleTensor) { - val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] -= - newOther.buffer.array()[this.bufferStart + i] + override fun TensorStructure.minusAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] -= + newOther.buffer.array()[tensor.bufferStart + i] } } - override fun DoubleTensor.times(other: DoubleTensor): DoubleTensor { - val broadcast = broadcastTensors(this, other) + override fun TensorStructure.times(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> @@ -51,16 +52,16 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun DoubleTensor.timesAssign(other: DoubleTensor) { - val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] *= - newOther.buffer.array()[this.bufferStart + i] + override fun TensorStructure.timesAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] *= + newOther.buffer.array()[tensor.bufferStart + i] } } - override fun DoubleTensor.div(other: DoubleTensor): DoubleTensor { - val broadcast = broadcastTensors(this, other) + override fun TensorStructure.div(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> @@ -70,11 +71,11 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun DoubleTensor.divAssign(other: DoubleTensor) { - val newOther = broadcastTo(other, this.shape) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] /= - newOther.buffer.array()[this.bufferStart + i] + override fun TensorStructure.divAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] /= + newOther.buffer.array()[tensor.bufferStart + i] } } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 9e393f1a8..2b61e10b2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -6,13 +6,13 @@ import space.kscience.kmath.tensors.TensorStructure public open class BufferedTensor( override val shape: IntArray, - public val buffer: MutableBuffer, + internal val buffer: MutableBuffer, internal val bufferStart: Int ) : TensorStructure { public val linearStructure: TensorLinearStructure get() = TensorLinearStructure(shape) - public val numel: Int + public val numElements: Int get() = linearStructure.size override fun get(index: IntArray): T = buffer[bufferStart + linearStructure.offset(index)] @@ -41,26 +41,6 @@ public class IntTensor internal constructor( this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) } -public class LongTensor internal constructor( - shape: IntArray, - buffer: LongArray, - offset: Int = 0 -) : BufferedTensor(shape, LongBuffer(buffer), offset) -{ - internal constructor(bufferedTensor: BufferedTensor): - this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) -} - -public class FloatTensor internal constructor( - shape: IntArray, - buffer: FloatArray, - offset: Int = 0 -) : BufferedTensor(shape, FloatBuffer(buffer), offset) -{ - internal constructor(bufferedTensor: BufferedTensor): - this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) -} - public class DoubleTensor internal constructor( shape: IntArray, buffer: DoubleArray, @@ -74,7 +54,23 @@ public class DoubleTensor internal constructor( } -internal fun BufferedTensor.asTensor(): IntTensor = IntTensor(this) -internal fun BufferedTensor.asTensor(): LongTensor = LongTensor(this) -internal fun BufferedTensor.asTensor(): FloatTensor = FloatTensor(this) -internal fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this) +internal inline fun BufferedTensor.asTensor(): IntTensor = IntTensor(this) +internal inline fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this) + +internal inline fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { + is BufferedTensor -> this + else -> BufferedTensor(this.shape, this.elements().map{ it.second }.toMutableList().asMutableBuffer(), 0) +} + +internal val TensorStructure.tensor: DoubleTensor + get() = when (this) { + is DoubleTensor -> this + else -> this.toBufferedTensor().asTensor() + } + +internal val TensorStructure.tensor: IntTensor + get() = when (this) { + is IntTensor -> this + else -> this.toBufferedTensor().asTensor() + } + diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt index b46c7fa9c..233217f2f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt @@ -1,45 +1,46 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.AnalyticTensorAlgebra +import space.kscience.kmath.tensors.TensorStructure import kotlin.math.* public class DoubleAnalyticTensorAlgebra: - AnalyticTensorAlgebra, + AnalyticTensorAlgebra, DoubleTensorAlgebra() { - override fun DoubleTensor.exp(): DoubleTensor = this.map(::exp) + override fun TensorStructure.exp(): DoubleTensor = tensor.map(::exp) - override fun DoubleTensor.log(): DoubleTensor = this.map(::ln) + override fun TensorStructure.log(): DoubleTensor = tensor.map(::ln) - override fun DoubleTensor.sqrt(): DoubleTensor = this.map(::sqrt) + override fun TensorStructure.sqrt(): DoubleTensor = tensor.map(::sqrt) - override fun DoubleTensor.cos(): DoubleTensor = this.map(::cos) + override fun TensorStructure.cos(): DoubleTensor = tensor.map(::cos) - override fun DoubleTensor.acos(): DoubleTensor = this.map(::acos) + override fun TensorStructure.acos(): DoubleTensor = tensor.map(::acos) - override fun DoubleTensor.cosh(): DoubleTensor = this.map(::cosh) + override fun TensorStructure.cosh(): DoubleTensor = tensor.map(::cosh) - override fun DoubleTensor.acosh(): DoubleTensor = this.map(::acosh) + override fun TensorStructure.acosh(): DoubleTensor = tensor.map(::acosh) - override fun DoubleTensor.sin(): DoubleTensor = this.map(::sin) + override fun TensorStructure.sin(): DoubleTensor = tensor.map(::sin) - override fun DoubleTensor.asin(): DoubleTensor = this.map(::asin) + override fun TensorStructure.asin(): DoubleTensor = tensor.map(::asin) - override fun DoubleTensor.sinh(): DoubleTensor = this.map(::sinh) + override fun TensorStructure.sinh(): DoubleTensor = tensor.map(::sinh) - override fun DoubleTensor.asinh(): DoubleTensor = this.map(::asinh) + override fun TensorStructure.asinh(): DoubleTensor = tensor.map(::asinh) - override fun DoubleTensor.tan(): DoubleTensor = this.map(::tan) + override fun TensorStructure.tan(): DoubleTensor = tensor.map(::tan) - override fun DoubleTensor.atan(): DoubleTensor = this.map(::atan) + override fun TensorStructure.atan(): DoubleTensor = tensor.map(::atan) - override fun DoubleTensor.tanh(): DoubleTensor = this.map(::tanh) + override fun TensorStructure.tanh(): DoubleTensor = tensor.map(::tanh) - override fun DoubleTensor.atanh(): DoubleTensor = this.map(::atanh) + override fun TensorStructure.atanh(): DoubleTensor = tensor.map(::atanh) - override fun DoubleTensor.ceil(): DoubleTensor = this.map(::ceil) + override fun TensorStructure.ceil(): DoubleTensor = tensor.map(::ceil) - override fun DoubleTensor.floor(): DoubleTensor = this.map(::floor) + override fun TensorStructure.floor(): DoubleTensor = tensor.map(::floor) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt index e72948c84..386fc2a1b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt @@ -3,44 +3,45 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.tensors.TensorStructure import kotlin.math.min public class DoubleLinearOpsTensorAlgebra : - LinearOpsTensorAlgebra, + LinearOpsTensorAlgebra, DoubleTensorAlgebra() { - override fun DoubleTensor.inv(): DoubleTensor = invLU(1e-9) + override fun TensorStructure.inv(): DoubleTensor = invLU(1e-9) - override fun DoubleTensor.det(): DoubleTensor = detLU(1e-9) + override fun TensorStructure.det(): DoubleTensor = detLU(1e-9) - public fun DoubleTensor.lu(epsilon: Double): Pair = - computeLU(this, epsilon) ?: + public fun TensorStructure.lu(epsilon: Double): Pair = + computeLU(tensor, epsilon) ?: throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon") - override fun DoubleTensor.lu(): Pair = lu(1e-9) + override fun TensorStructure.lu(): Pair = lu(1e-9) override fun luPivot( - luTensor: DoubleTensor, - pivotsTensor: IntTensor + luTensor: TensorStructure, + pivotsTensor: TensorStructure ): Triple { //todo checks checkSquareMatrix(luTensor.shape) check( luTensor.shape.dropLast(2).toIntArray() contentEquals pivotsTensor.shape.dropLast(1).toIntArray() || luTensor.shape.last() == pivotsTensor.shape.last() - 1 - ) { "Bed shapes ((" } //todo rewrite + ) { "Bad shapes ((" } //todo rewrite val n = luTensor.shape.last() val pTensor = luTensor.zeroesLike() - for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) + for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.tensor.vectorSequence())) pivInit(p.as2D(), pivot.as1D(), n) val lTensor = luTensor.zeroesLike() val uTensor = luTensor.zeroesLike() for ((pairLU, lu) in lTensor.matrixSequence().zip(uTensor.matrixSequence()) - .zip(luTensor.matrixSequence())) { + .zip(luTensor.tensor.matrixSequence())) { val (l, u) = pairLU luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) } @@ -49,26 +50,26 @@ public class DoubleLinearOpsTensorAlgebra : } - public fun DoubleTensor.cholesky(epsilon: Double): DoubleTensor { + public fun TensorStructure.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) - checkPositiveDefinite(this, epsilon) + checkPositiveDefinite(tensor, epsilon) val n = shape.last() val lTensor = zeroesLike() - for ((a, l) in this.matrixSequence().zip(lTensor.matrixSequence())) + for ((a, l) in tensor.matrixSequence().zip(lTensor.matrixSequence())) for (i in 0 until n) choleskyHelper(a.as2D(), l.as2D(), n) return lTensor } - override fun DoubleTensor.cholesky(): DoubleTensor = cholesky(1e-6) + override fun TensorStructure.cholesky(): DoubleTensor = cholesky(1e-6) - override fun DoubleTensor.qr(): Pair { + override fun TensorStructure.qr(): Pair { checkSquareMatrix(shape) val qTensor = zeroesLike() val rTensor = zeroesLike() - val seq = matrixSequence().zip((qTensor.matrixSequence().zip(rTensor.matrixSequence()))) + val seq = tensor.matrixSequence().zip((qTensor.matrixSequence().zip(rTensor.matrixSequence()))) for ((matrix, qr) in seq) { val (q, r) = qr qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) @@ -76,18 +77,18 @@ public class DoubleLinearOpsTensorAlgebra : return qTensor to rTensor } - override fun DoubleTensor.svd(): Triple = + override fun TensorStructure.svd(): Triple = svd(epsilon = 1e-10) - public fun DoubleTensor.svd(epsilon: Double): Triple { - val size = this.linearStructure.dim - val commonShape = this.shape.sliceArray(0 until size - 2) - val (n, m) = this.shape.sliceArray(size - 2 until size) + public fun TensorStructure.svd(epsilon: Double): Triple { + val size = tensor.linearStructure.dim + val commonShape = tensor.shape.sliceArray(0 until size - 2) + val (n, m) = tensor.shape.sliceArray(size - 2 until size) val resU = zeros(commonShape + intArrayOf(min(n, m), n)) val resS = zeros(commonShape + intArrayOf(min(n, m))) val resV = zeros(commonShape + intArrayOf(min(n, m), m)) - for ((matrix, USV) in this.matrixSequence() + for ((matrix, USV) in tensor.matrixSequence() .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) { val size = matrix.shape.reduce { acc, i -> acc * i } val curMatrix = DoubleTensor( @@ -99,13 +100,13 @@ public class DoubleLinearOpsTensorAlgebra : return Triple(resU.transpose(), resS, resV.transpose()) } - override fun DoubleTensor.symEig(): Pair = + override fun TensorStructure.symEig(): Pair = symEig(epsilon = 1e-15) //http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html - public fun DoubleTensor.symEig(epsilon: Double): Pair { - checkSymmetric(this, epsilon) - val (u, s, v) = this.svd(epsilon) + public fun TensorStructure.symEig(epsilon: Double): Pair { + checkSymmetric(tensor, epsilon) + val (u, s, v) = tensor.svd(epsilon) val shp = s.shape + intArrayOf(1) val utv = u.transpose() dot v val n = s.shape.last() @@ -116,11 +117,11 @@ public class DoubleLinearOpsTensorAlgebra : return Pair(eig, v) } - public fun DoubleTensor.detLU(epsilon: Double = 1e-9): DoubleTensor { + public fun TensorStructure.detLU(epsilon: Double = 1e-9): DoubleTensor { - checkSquareMatrix(this.shape) - val luTensor = this.copy() - val pivotsTensor = this.setUpPivots() + checkSquareMatrix(tensor.shape) + val luTensor = tensor.copy() + val pivotsTensor = tensor.setUpPivots() val n = shape.size @@ -141,7 +142,7 @@ public class DoubleLinearOpsTensorAlgebra : return detTensor } - public fun DoubleTensor.invLU(epsilon: Double = 1e-9): DoubleTensor { + public fun TensorStructure.invLU(epsilon: Double = 1e-9): DoubleTensor { val (luTensor, pivotsTensor) = lu(epsilon) val invTensor = luTensor.zeroesLike() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 8f355dd3d..7544bf68e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,16 +1,18 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra import space.kscience.kmath.nd.as2D +import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra +import space.kscience.kmath.tensors.TensorStructure import kotlin.math.abs -public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { +public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { - override fun DoubleTensor.value(): Double { - check(this.shape contentEquals intArrayOf(1)) { + + override fun TensorStructure.value(): Double { + check(tensor.shape contentEquals intArrayOf(1)) { "Inconsistent value for tensor of shape ${shape.toList()}" } - return this.buffer.array()[this.bufferStart] + return tensor.buffer.array()[tensor.bufferStart] } public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor { @@ -20,11 +22,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra.get(i: Int): DoubleTensor { + val lastShape = tensor.shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) - val newStart = newShape.reduce(Int::times) * i + this.bufferStart - return DoubleTensor(newShape, this.buffer.array(), newStart) + val newStart = newShape.reduce(Int::times) * i + tensor.bufferStart + return DoubleTensor(newShape, tensor.buffer.array(), newStart) } public fun full(value: Double, shape: IntArray): DoubleTensor { @@ -33,19 +35,19 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra.fullLike(value: Double): DoubleTensor { + val shape = tensor.shape + val buffer = DoubleArray(tensor.numElements) { value } return DoubleTensor(shape, buffer) } public fun zeros(shape: IntArray): DoubleTensor = full(0.0, shape) - public fun DoubleTensor.zeroesLike(): DoubleTensor = this.fullLike(0.0) + public fun TensorStructure.zeroesLike(): DoubleTensor = tensor.fullLike(0.0) public fun ones(shape: IntArray): DoubleTensor = full(1.0, shape) - public fun DoubleTensor.onesLike(): DoubleTensor = this.fullLike(1.0) + public fun TensorStructure.onesLike(): DoubleTensor = tensor.fullLike(1.0) public fun eye(n: Int): DoubleTensor { val shape = intArrayOf(n, n) @@ -57,200 +59,200 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra.copy(): DoubleTensor { + return DoubleTensor(tensor.shape, tensor.buffer.array().copyOf(), tensor.bufferStart) } - override fun Double.plus(other: DoubleTensor): DoubleTensor { - val resBuffer = DoubleArray(other.linearStructure.size) { i -> - other.buffer.array()[other.bufferStart + i] + this + override fun Double.plus(other: TensorStructure): DoubleTensor { + val resBuffer = DoubleArray(other.tensor.numElements) { i -> + other.tensor.buffer.array()[other.tensor.bufferStart + i] + this } return DoubleTensor(other.shape, resBuffer) } - override fun DoubleTensor.plus(value: Double): DoubleTensor = value + this + override fun TensorStructure.plus(value: Double): DoubleTensor = value + tensor - override fun DoubleTensor.plus(other: DoubleTensor): DoubleTensor { - checkShapesCompatible(this, other) - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[i] + other.buffer.array()[i] + override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { + checkShapesCompatible(tensor, other.tensor) + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[i] + other.tensor.buffer.array()[i] } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.plusAssign(value: Double) { - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] += value + override fun TensorStructure.plusAssign(value: Double) { + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] += value } } - override fun DoubleTensor.plusAssign(other: DoubleTensor) { - checkShapesCompatible(this, other) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] += - other.buffer.array()[this.bufferStart + i] + override fun TensorStructure.plusAssign(other: TensorStructure) { + checkShapesCompatible(tensor, other.tensor) + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] += + other.tensor.buffer.array()[tensor.bufferStart + i] } } - override fun Double.minus(other: DoubleTensor): DoubleTensor { - val resBuffer = DoubleArray(other.linearStructure.size) { i -> - this - other.buffer.array()[other.bufferStart + i] + override fun Double.minus(other: TensorStructure): DoubleTensor { + val resBuffer = DoubleArray(other.tensor.numElements) { i -> + this - other.tensor.buffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } - override fun DoubleTensor.minus(value: Double): DoubleTensor { - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[this.bufferStart + i] - value + override fun TensorStructure.minus(value: Double): DoubleTensor { + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[tensor.bufferStart + i] - value } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.minus(other: DoubleTensor): DoubleTensor { - checkShapesCompatible(this, other) - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[i] - other.buffer.array()[i] + override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { + checkShapesCompatible(tensor, other) + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[i] - other.tensor.buffer.array()[i] } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.minusAssign(value: Double) { - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] -= value + override fun TensorStructure.minusAssign(value: Double) { + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] -= value } } - override fun DoubleTensor.minusAssign(other: DoubleTensor) { - checkShapesCompatible(this, other) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] -= - other.buffer.array()[this.bufferStart + i] + override fun TensorStructure.minusAssign(other: TensorStructure) { + checkShapesCompatible(tensor, other) + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] -= + other.tensor.buffer.array()[tensor.bufferStart + i] } } - override fun Double.times(other: DoubleTensor): DoubleTensor { - val resBuffer = DoubleArray(other.linearStructure.size) { i -> - other.buffer.array()[other.bufferStart + i] * this + override fun Double.times(other: TensorStructure): DoubleTensor { + val resBuffer = DoubleArray(other.tensor.numElements) { i -> + other.tensor.buffer.array()[other.tensor.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) } - override fun DoubleTensor.times(value: Double): DoubleTensor = value * this + override fun TensorStructure.times(value: Double): DoubleTensor = value * tensor - override fun DoubleTensor.times(other: DoubleTensor): DoubleTensor { - checkShapesCompatible(this, other) - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[this.bufferStart + i] * - other.buffer.array()[other.bufferStart + i] + override fun TensorStructure.times(other: TensorStructure): DoubleTensor { + checkShapesCompatible(tensor, other) + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[tensor.bufferStart + i] * + other.tensor.buffer.array()[other.tensor.bufferStart + i] } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.timesAssign(value: Double) { - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] *= value + override fun TensorStructure.timesAssign(value: Double) { + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] *= value } } - override fun DoubleTensor.timesAssign(other: DoubleTensor) { - checkShapesCompatible(this, other) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] *= - other.buffer.array()[this.bufferStart + i] + override fun TensorStructure.timesAssign(other: TensorStructure) { + checkShapesCompatible(tensor, other) + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] *= + other.tensor.buffer.array()[tensor.bufferStart + i] } } - override fun DoubleTensor.div(value: Double): DoubleTensor { - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[this.bufferStart + i] / value + override fun TensorStructure.div(value: Double): DoubleTensor { + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[tensor.bufferStart + i] / value } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.div(other: DoubleTensor): DoubleTensor { - checkShapesCompatible(this, other) - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[other.bufferStart + i] / - other.buffer.array()[other.bufferStart + i] + override fun TensorStructure.div(other: TensorStructure): DoubleTensor { + checkShapesCompatible(tensor, other) + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[other.tensor.bufferStart + i] / + other.tensor.buffer.array()[other.tensor.bufferStart + i] } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.divAssign(value: Double) { - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] /= value + override fun TensorStructure.divAssign(value: Double) { + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] /= value } } - override fun DoubleTensor.divAssign(other: DoubleTensor) { - checkShapesCompatible(this, other) - for (i in 0 until this.linearStructure.size) { - this.buffer.array()[this.bufferStart + i] /= - other.buffer.array()[this.bufferStart + i] + override fun TensorStructure.divAssign(other: TensorStructure) { + checkShapesCompatible(tensor, other) + for (i in 0 until tensor.numElements) { + tensor.buffer.array()[tensor.bufferStart + i] /= + other.tensor.buffer.array()[tensor.bufferStart + i] } } - override fun DoubleTensor.unaryMinus(): DoubleTensor { - val resBuffer = DoubleArray(this.linearStructure.size) { i -> - this.buffer.array()[this.bufferStart + i].unaryMinus() + override fun TensorStructure.unaryMinus(): DoubleTensor { + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[tensor.bufferStart + i].unaryMinus() } - return DoubleTensor(this.shape, resBuffer) + return DoubleTensor(tensor.shape, resBuffer) } - override fun DoubleTensor.transpose(i: Int, j: Int): DoubleTensor { - val ii = minusIndex(i) - val jj = minusIndex(j) - checkTranspose(this.dimension, ii, jj) - val n = this.linearStructure.size + override fun TensorStructure.transpose(i: Int, j: Int): DoubleTensor { + val ii = tensor.minusIndex(i) + val jj = tensor.minusIndex(j) + checkTranspose(tensor.dimension, ii, jj) + val n = tensor.numElements val resBuffer = DoubleArray(n) - val resShape = this.shape.copyOf() + val resShape = tensor.shape.copyOf() resShape[ii] = resShape[jj].also { resShape[jj] = resShape[ii] } val resTensor = DoubleTensor(resShape, resBuffer) for (offset in 0 until n) { - val oldMultiIndex = this.linearStructure.index(offset) + val oldMultiIndex = tensor.linearStructure.index(offset) val newMultiIndex = oldMultiIndex.copyOf() newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } val linearIndex = resTensor.linearStructure.offset(newMultiIndex) resTensor.buffer.array()[linearIndex] = - this.buffer.array()[this.bufferStart + offset] + tensor.buffer.array()[tensor.bufferStart + offset] } return resTensor } - override fun DoubleTensor.view(shape: IntArray): DoubleTensor { - checkView(this, shape) - return DoubleTensor(shape, this.buffer.array(), this.bufferStart) + override fun TensorStructure.view(shape: IntArray): DoubleTensor { + checkView(tensor, shape) + return DoubleTensor(shape, tensor.buffer.array(), tensor.bufferStart) } - override fun DoubleTensor.viewAs(other: DoubleTensor): DoubleTensor { - return this.view(other.shape) + override fun TensorStructure.viewAs(other: TensorStructure): DoubleTensor { + return tensor.view(other.shape) } - override infix fun DoubleTensor.dot(other: DoubleTensor): DoubleTensor { - if (this.shape.size == 1 && other.shape.size == 1) { - return DoubleTensor(intArrayOf(1), doubleArrayOf(this.times(other).buffer.array().sum())) + override infix fun TensorStructure.dot(other: TensorStructure): DoubleTensor { + if (tensor.shape.size == 1 && other.shape.size == 1) { + return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.buffer.array().sum())) } - var newThis = this.copy() + var newThis = tensor.copy() var newOther = other.copy() var penultimateDim = false var lastDim = false - if (this.shape.size == 1) { + if (tensor.shape.size == 1) { penultimateDim = true - newThis = this.view(intArrayOf(1) + this.shape) + newThis = tensor.view(intArrayOf(1) + tensor.shape) } if (other.shape.size == 1) { lastDim = true - newOther = other.view(other.shape + intArrayOf(1)) + newOther = other.tensor.view(other.shape + intArrayOf(1)) } - val broadcastTensors = broadcastOuterTensors(newThis, newOther) + val broadcastTensors = broadcastOuterTensors(newThis.tensor, newOther.tensor) newThis = broadcastTensors[0] newOther = broadcastTensors[1] @@ -284,10 +286,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra, offset: Int, dim1: Int, dim2: Int): + DoubleTensor { val n = diagonalEntries.shape.size + val d1 = minusIndexFrom(n + 1, dim1) + val d2 = minusIndexFrom(n + 1, dim2) + if (d1 == d2) { throw RuntimeException("Diagonal dimensions cannot be identical $d1, $d2") } @@ -300,7 +304,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra greaterDim) { realOffset *= -1 - lessDim = greaterDim.also {greaterDim = lessDim} + lessDim = greaterDim.also { greaterDim = lessDim } } val resShape = diagonalEntries.shape.slice(0 until lessDim).toIntArray() + @@ -310,13 +314,13 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra Double): DoubleTensor { + public fun TensorStructure.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( - this.shape, - this.buffer.array().map { transform(it) }.toDoubleArray(), - this.bufferStart + tensor.shape, + tensor.buffer.array().map { transform(it) }.toDoubleArray(), + tensor.bufferStart ) } - public fun DoubleTensor.eq(other: DoubleTensor, delta: Double): Boolean { - return this.eq(other) { x, y -> abs(x - y) < delta } + public fun TensorStructure.eq(other: TensorStructure, delta: Double): Boolean { + return tensor.eq(other) { x, y -> abs(x - y) < delta } } - public fun DoubleTensor.eq(other: DoubleTensor): Boolean = this.eq(other, 1e-5) + public fun TensorStructure.eq(other: TensorStructure): Boolean = tensor.eq(other, 1e-5) - private fun DoubleTensor.eq(other: DoubleTensor, eqFunction: (Double, Double) -> Boolean): Boolean { - checkShapesCompatible(this, other) - val n = this.linearStructure.size - if (n != other.linearStructure.size) { + private fun TensorStructure.eq( + other: TensorStructure, + eqFunction: (Double, Double) -> Boolean + ): Boolean { + checkShapesCompatible(tensor, other) + val n = tensor.numElements + if (n != other.tensor.numElements) { return false } for (i in 0 until n) { - if (!eqFunction(this.buffer[this.bufferStart + i], other.buffer[other.bufferStart + i])) { + if (!eqFunction(tensor.buffer[tensor.bufferStart + i], other.tensor.buffer[other.tensor.bufferStart + i])) { return false } } @@ -362,8 +369,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra.randNormalLike(seed: Long = 0): DoubleTensor = + DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index 730b6ed9a..28828eb09 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -1,54 +1,40 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.tensors.TensorAlgebra import space.kscience.kmath.tensors.TensorStructure -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkEmptyShape(shape: IntArray): Unit = +internal inline fun checkEmptyShape(shape: IntArray): Unit = check(shape.isNotEmpty()) { "Illegal empty shape provided" } -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = +internal inline fun checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = check(buffer.isNotEmpty()) { "Illegal empty buffer provided" } -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = +internal inline fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = check(buffer.size == shape.reduce(Int::times)) { "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" } -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkShapesCompatible(a: TensorType, b: TensorType): Unit = +internal inline fun checkShapesCompatible(a: TensorStructure, b: TensorStructure): Unit = check(a.shape contentEquals b.shape) { "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " } -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkTranspose(dim: Int, i: Int, j: Int): Unit = +internal inline fun checkTranspose(dim: Int, i: Int, j: Int): Unit = check((i < dim) and (j < dim)) { "Cannot transpose $i to $j for a tensor of dim $dim" } -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkView(a: TensorType, shape: IntArray): Unit = +internal inline fun checkView(a: TensorStructure, shape: IntArray): Unit = check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) -internal inline fun , - TorchTensorAlgebraType : TensorAlgebra> - TorchTensorAlgebraType.checkSquareMatrix(shape: IntArray): Unit { + +internal inline fun checkSquareMatrix(shape: IntArray): Unit { val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n instead" @@ -58,16 +44,19 @@ internal inline fun , } } -internal inline fun DoubleTensorAlgebra.checkSymmetric(tensor: DoubleTensor, epsilon: Double = 1e-6): Unit = +internal inline fun DoubleTensorAlgebra.checkSymmetric( + tensor: TensorStructure, epsilon: Double = 1e-6 +): Unit = check(tensor.eq(tensor.transpose(), epsilon)) { "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( - tensor: DoubleTensor, epsilon: Double = 1e-6): Unit { + tensor: DoubleTensor, epsilon: Double = 1e-6 +): Unit { checkSymmetric(tensor, epsilon) - for( mat in tensor.matrixSequence()) - check(mat.asTensor().detLU().value() > 0.0){ + for (mat in tensor.matrixSequence()) + check(mat.asTensor().detLU().value() > 0.0) { "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt index ba5e0caaf..166f1d6c4 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linutils.kt @@ -14,7 +14,7 @@ internal inline fun BufferedTensor.vectorSequence(): Sequence BufferedTensor.matrixSequence(): Sequence= 0) i else { ii } -internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.linearStructure.dim, i) +internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.dimension, i) internal inline fun format(value: Double, digits: Int = 4): String { val ten = 10.0 @@ -111,7 +111,7 @@ internal inline fun DoubleTensor.toPrettyString(): String = buildString { } offset += vectorSize // todo refactor - if (this@toPrettyString.numel == offset) { + if (this@toPrettyString.numElements == offset) { break } append(",\n") From 559e8b24ab6189b523e3707b605b7f2c75c8b92c Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 21 Apr 2021 23:44:39 +0300 Subject: [PATCH 236/393] rework structure + fixes --- .../{ => api}/AnalyticTensorAlgebra.kt | 7 +- .../{ => api}/LinearOpsTensorAlgebra.kt | 7 +- .../kmath/tensors/{ => api}/TensorAlgebra.kt | 11 +- .../{ => api}/TensorPartialDivisionAlgebra.kt | 9 +- .../tensors/{ => api}/TensorStructure.kt | 2 +- .../kmath/tensors/core/BufferedTensor.kt | 3 +- .../algebras/BroadcastDoubleTensorAlgebra.kt | 89 ++++++++++ .../DoubleAnalyticTensorAlgebra.kt | 13 +- .../DoubleLinearOpsTensorAlgebra.kt | 27 +++- .../{ => algebras}/DoubleTensorAlgebra.kt | 27 +++- .../{ => algebras}/TensorLinearStructure.kt | 7 +- ...ubleTensorAlgebra.kt => broadcastUtils.kt} | 153 ++++-------------- .../kscience/kmath/tensors/core/checks.kt | 4 +- .../tensors/core/{linutils.kt => linUtils.kt} | 10 +- .../kscience/kmath/tensors/core/utils.kt | 1 - .../kmath/tensors/core/TestBroadcasting.kt | 1 + .../core/TestDoubleAnalyticTensorAlgebra.kt | 1 + .../core/TestDoubleLinearOpsAlgebra.kt | 3 +- .../kmath/tensors/core/TestDoubleTensor.kt | 2 +- .../tensors/core/TestDoubleTensorAlgebra.kt | 20 ++- 20 files changed, 237 insertions(+), 160 deletions(-) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => api}/AnalyticTensorAlgebra.kt (91%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => api}/LinearOpsTensorAlgebra.kt (86%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => api}/TensorAlgebra.kt (89%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => api}/TensorPartialDivisionAlgebra.kt (64%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/{ => api}/TensorStructure.kt (73%) create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => algebras}/DoubleAnalyticTensorAlgebra.kt (77%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => algebras}/DoubleLinearOpsTensorAlgebra.kt (84%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => algebras}/DoubleTensorAlgebra.kt (92%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => algebras}/TensorLinearStructure.kt (90%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{BroadcastDoubleTensorAlgebra.kt => broadcastUtils.kt} (52%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{linutils.kt => linUtils.kt} (97%) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt similarity index 91% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 2a8b228f4..315f39027 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -1,4 +1,9 @@ -package space.kscience.kmath.tensors +/* + * 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.tensors.api public interface AnalyticTensorAlgebra : diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt similarity index 86% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 8ca8945a5..5cd48ca78 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -1,4 +1,9 @@ -package space.kscience.kmath.tensors +/* + * 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.tensors.api public interface LinearOpsTensorAlgebra : diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt similarity index 89% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index f64d49dd8..c1657d916 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -1,4 +1,9 @@ -package space.kscience.kmath.tensors +/* + * 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.tensors.api // https://proofwiki.org/wiki/Definition:Algebra_over_Ring public interface TensorAlgebra { @@ -40,7 +45,9 @@ public interface TensorAlgebra { //https://pytorch.org/docs/stable/generated/torch.diag_embed.html public fun diagonalEmbedding( diagonalEntries: TensorStructure, - offset: Int = 0, dim1: Int = -2, dim2: Int = -1 + offset: Int = 0, + dim1: Int = -2, + dim2: Int = -1 ): TensorStructure } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt similarity index 64% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt index b37ac6b6e..075e86e61 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt @@ -1,8 +1,13 @@ -package space.kscience.kmath.tensors +/* + * 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.tensors.api // https://proofwiki.org/wiki/Definition:Division_Algebra public interface TensorPartialDivisionAlgebra : - TensorAlgebra { + TensorAlgebra { public operator fun TensorStructure.div(value: T): TensorStructure public operator fun TensorStructure.div(other: TensorStructure): TensorStructure public operator fun TensorStructure.divAssign(value: T) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorStructure.kt similarity index 73% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorStructure.kt index 64c4d98b8..edecd6383 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/TensorStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorStructure.kt @@ -1,4 +1,4 @@ -package space.kscience.kmath.tensors +package space.kscience.kmath.tensors.api import space.kscience.kmath.nd.MutableStructureND diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 2b61e10b2..5c0d9c4ea 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,7 +1,8 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.structures.* -import space.kscience.kmath.tensors.TensorStructure +import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure public open class BufferedTensor( diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt new file mode 100644 index 000000000..1b00197ff --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -0,0 +1,89 @@ +/* + * 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.tensors.core.algebras + +import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.broadcastTensors +import space.kscience.kmath.tensors.core.broadcastTo + +public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { + + override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + newThis.buffer.array()[i] + newOther.buffer.array()[i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun TensorStructure.plusAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] += + newOther.buffer.array()[tensor.bufferStart + i] + } + } + + override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + newThis.buffer.array()[i] - newOther.buffer.array()[i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun TensorStructure.minusAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] -= + newOther.buffer.array()[tensor.bufferStart + i] + } + } + + override fun TensorStructure.times(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + newThis.buffer.array()[newThis.bufferStart + i] * + newOther.buffer.array()[newOther.bufferStart + i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun TensorStructure.timesAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] *= + newOther.buffer.array()[tensor.bufferStart + i] + } + } + + override fun TensorStructure.div(other: TensorStructure): DoubleTensor { + val broadcast = broadcastTensors(tensor, other.tensor) + val newThis = broadcast[0] + val newOther = broadcast[1] + val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + newThis.buffer.array()[newOther.bufferStart + i] / + newOther.buffer.array()[newOther.bufferStart + i] + } + return DoubleTensor(newThis.shape, resBuffer) + } + + override fun TensorStructure.divAssign(other: TensorStructure) { + val newOther = broadcastTo(other.tensor, tensor.shape) + for (i in 0 until tensor.linearStructure.size) { + tensor.buffer.array()[tensor.bufferStart + i] /= + newOther.buffer.array()[tensor.bufferStart + i] + } + } + +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt similarity index 77% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 233217f2f..7d1cceb15 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -1,7 +1,14 @@ -package space.kscience.kmath.tensors.core +/* + * 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. + */ -import space.kscience.kmath.tensors.AnalyticTensorAlgebra -import space.kscience.kmath.tensors.TensorStructure +package space.kscience.kmath.tensors.core.algebras + +import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra +import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.tensor import kotlin.math.* public class DoubleAnalyticTensorAlgebra: diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt similarity index 84% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 386fc2a1b..62629f3db 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -1,9 +1,23 @@ -package space.kscience.kmath.tensors.core +/* + * 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. + */ -import space.kscience.kmath.tensors.LinearOpsTensorAlgebra +package space.kscience.kmath.tensors.core.algebras + +import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D -import space.kscience.kmath.tensors.TensorStructure +import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.checkSquareMatrix +import space.kscience.kmath.tensors.core.choleskyHelper +import space.kscience.kmath.tensors.core.cleanSymHelper +import space.kscience.kmath.tensors.core.luHelper +import space.kscience.kmath.tensors.core.luMatrixDet +import space.kscience.kmath.tensors.core.luMatrixInv +import space.kscience.kmath.tensors.core.luPivotHelper +import space.kscience.kmath.tensors.core.pivInit import kotlin.math.min @@ -25,12 +39,11 @@ public class DoubleLinearOpsTensorAlgebra : luTensor: TensorStructure, pivotsTensor: TensorStructure ): Triple { - //todo checks checkSquareMatrix(luTensor.shape) check( luTensor.shape.dropLast(2).toIntArray() contentEquals pivotsTensor.shape.dropLast(1).toIntArray() || luTensor.shape.last() == pivotsTensor.shape.last() - 1 - ) { "Bad shapes ((" } //todo rewrite + ) { "Inappropriate shapes of input tensors" } val n = luTensor.shape.last() val pTensor = luTensor.zeroesLike() @@ -90,10 +103,10 @@ public class DoubleLinearOpsTensorAlgebra : for ((matrix, USV) in tensor.matrixSequence() .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) { - val size = matrix.shape.reduce { acc, i -> acc * i } + val matrixSize = matrix.shape.reduce { acc, i -> acc * i } val curMatrix = DoubleTensor( matrix.shape, - matrix.buffer.array().slice(matrix.bufferStart until matrix.bufferStart + size).toDoubleArray() + matrix.buffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize).toDoubleArray() ) svdHelper(curMatrix, USV, m, n, epsilon) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt similarity index 92% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 7544bf68e..651db2c21 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -1,8 +1,24 @@ -package space.kscience.kmath.tensors.core +/* + * 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.tensors.core.algebras import space.kscience.kmath.nd.as2D -import space.kscience.kmath.tensors.TensorPartialDivisionAlgebra -import space.kscience.kmath.tensors.TensorStructure +import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra +import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.broadcastOuterTensors +import space.kscience.kmath.tensors.core.checkBufferShapeConsistency +import space.kscience.kmath.tensors.core.checkEmptyDoubleBuffer +import space.kscience.kmath.tensors.core.checkEmptyShape +import space.kscience.kmath.tensors.core.checkShapesCompatible +import space.kscience.kmath.tensors.core.checkTranspose +import space.kscience.kmath.tensors.core.checkView +import space.kscience.kmath.tensors.core.dotHelper +import space.kscience.kmath.tensors.core.getRandomNormals +import space.kscience.kmath.tensors.core.minusIndexFrom import kotlin.math.abs public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { @@ -263,7 +279,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { if (m1 != m2) { throw RuntimeException("Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)") } - val m = m1 val resShape = newThis.shape.sliceArray(0..(newThis.shape.size - 2)) + intArrayOf(newOther.shape.last()) val resSize = resShape.reduce { acc, i -> acc * i } @@ -271,7 +286,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { for ((res, ab) in resTensor.matrixSequence().zip(newThis.matrixSequence().zip(newOther.matrixSequence()))) { val (a, b) = ab - dotHelper(a.as2D(), b.as2D(), res.as2D(), l, m, n) + dotHelper(a.as2D(), b.as2D(), res.as2D(), l, m1, n) } if (penultimateDim) { @@ -347,7 +362,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return tensor.eq(other) { x, y -> abs(x - y) < delta } } - public fun TensorStructure.eq(other: TensorStructure): Boolean = tensor.eq(other, 1e-5) + public infix fun TensorStructure.eq(other: TensorStructure): Boolean = tensor.eq(other, 1e-5) private fun TensorStructure.eq( other: TensorStructure, diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt similarity index 90% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index 47745c2be..b16739892 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -1,4 +1,9 @@ -package space.kscience.kmath.tensors.core +/* + * 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.tensors.core.algebras import kotlin.math.max diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt similarity index 52% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt index 53c385197..4378e9ac9 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt @@ -1,89 +1,31 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.tensors.TensorStructure +import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra import kotlin.math.max -public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { - - override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { - val broadcast = broadcastTensors(tensor, other.tensor) - val newThis = broadcast[0] - val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[i] + newOther.buffer.array()[i] - } - return DoubleTensor(newThis.shape, resBuffer) - } - - override fun TensorStructure.plusAssign(other: TensorStructure) { - val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] += - newOther.buffer.array()[tensor.bufferStart + i] - } - } - - override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { - val broadcast = broadcastTensors(tensor, other.tensor) - val newThis = broadcast[0] - val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[i] - newOther.buffer.array()[i] - } - return DoubleTensor(newThis.shape, resBuffer) - } - - override fun TensorStructure.minusAssign(other: TensorStructure) { - val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] -= - newOther.buffer.array()[tensor.bufferStart + i] - } - } - - override fun TensorStructure.times(other: TensorStructure): DoubleTensor { - val broadcast = broadcastTensors(tensor, other.tensor) - val newThis = broadcast[0] - val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[newThis.bufferStart + i] * - newOther.buffer.array()[newOther.bufferStart + i] - } - return DoubleTensor(newThis.shape, resBuffer) - } - - override fun TensorStructure.timesAssign(other: TensorStructure) { - val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] *= - newOther.buffer.array()[tensor.bufferStart + i] - } - } - - override fun TensorStructure.div(other: TensorStructure): DoubleTensor { - val broadcast = broadcastTensors(tensor, other.tensor) - val newThis = broadcast[0] - val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[newOther.bufferStart + i] / - newOther.buffer.array()[newOther.bufferStart + i] - } - return DoubleTensor(newThis.shape, resBuffer) - } - - override fun TensorStructure.divAssign(other: TensorStructure) { - val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] /= - newOther.buffer.array()[tensor.bufferStart + i] - } - } - -} - public inline fun BroadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorAlgebra.() -> R): R = BroadcastDoubleTensorAlgebra().block() +internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) { + for (linearIndex in 0 until linearSize) { + val totalMultiIndex = resTensor.linearStructure.index(linearIndex) + val curMultiIndex = tensor.shape.copyOf() + + val offset = totalMultiIndex.size - curMultiIndex.size + + for (i in curMultiIndex.indices) { + if (curMultiIndex[i] != 1) { + curMultiIndex[i] = totalMultiIndex[i + offset] + } else { + curMultiIndex[i] = 0 + } + } + + val curLinearIndex = tensor.linearStructure.offset(curMultiIndex) + resTensor.buffer.array()[linearIndex] = + tensor.buffer.array()[tensor.bufferStart + curLinearIndex] + } +} internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { var totalDim = 0 @@ -129,24 +71,7 @@ internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): Doubl } } - for (linearIndex in 0 until n) { - val totalMultiIndex = resTensor.linearStructure.index(linearIndex) - val curMultiIndex = tensor.shape.copyOf() - - val offset = totalMultiIndex.size - curMultiIndex.size - - for (i in curMultiIndex.indices) { - if (curMultiIndex[i] != 1) { - curMultiIndex[i] = totalMultiIndex[i + offset] - } else { - curMultiIndex[i] = 0 - } - } - - val curLinearIndex = tensor.linearStructure.offset(curMultiIndex) - resTensor.buffer.array()[linearIndex] = - tensor.buffer.array()[tensor.bufferStart + curLinearIndex] - } + multiIndexBroadCasting(tensor, resTensor, n) return resTensor } @@ -157,25 +82,7 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List(0) for (tensor in tensors) { val resTensor = DoubleTensor(totalShape, DoubleArray(n)) - - for (linearIndex in 0 until n) { - val totalMultiIndex = resTensor.linearStructure.index(linearIndex) - val curMultiIndex = tensor.shape.copyOf() - - val offset = totalMultiIndex.size - curMultiIndex.size - - for (i in curMultiIndex.indices) { - if (curMultiIndex[i] != 1) { - curMultiIndex[i] = totalMultiIndex[i + offset] - } else { - curMultiIndex[i] = 0 - } - } - - val curLinearIndex = tensor.linearStructure.offset(curMultiIndex) - resTensor.buffer.array()[linearIndex] = - tensor.buffer.array()[tensor.bufferStart + curLinearIndex] - } + multiIndexBroadCasting(tensor, resTensor, n) res.add(resTensor) } @@ -208,7 +115,7 @@ internal inline fun broadcastOuterTensors(vararg tensors: DoubleTensor): List BufferedTensor.matrixSequence(): Sequence BufferedTensor.forEachVector(vectorAction: (BufferedTensor) -> Unit): Unit { +internal inline fun BufferedTensor.forEachVector(vectorAction: (BufferedTensor) -> Unit) { for (vector in vectorSequence()) { vectorAction(vector) } } -internal inline fun BufferedTensor.forEachMatrix(matrixAction: (BufferedTensor) -> Unit): Unit { +internal inline fun BufferedTensor.forEachMatrix(matrixAction: (BufferedTensor) -> Unit) { for (matrix in matrixSequence()) { matrixAction(matrix) } @@ -284,7 +286,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( matrix: DoubleTensor, USV: Pair, Pair, BufferedTensor>>, m: Int, n: Int, epsilon: Double -): Unit { +) { val res = ArrayList>(0) val (matrixU, SV) = USV val (matrixS, matrixV) = SV @@ -332,7 +334,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( } } -internal inline fun cleanSymHelper(matrix: MutableStructure2D, n: Int): Unit { +internal inline fun cleanSymHelper(matrix: MutableStructure2D, n: Int) { for (i in 0 until n) for (j in 0 until n) { if (i == j) { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index ac823185b..d7d006e42 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -110,7 +110,6 @@ internal inline fun DoubleTensor.toPrettyString(): String = buildString { charOffset -=1 } offset += vectorSize - // todo refactor if (this@toPrettyString.numElements == offset) { break } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 41c9b72f7..d677f6966 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.test.Test import kotlin.test.assertTrue diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 4dcdb7848..060bc1607 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import kotlin.math.abs import kotlin.math.exp import kotlin.test.Test diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index d19d0b6f6..6120f0e4a 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra import kotlin.math.abs import kotlin.test.Test import kotlin.test.assertEquals @@ -125,8 +126,6 @@ class TestDoubleLinearOpsTensorAlgebra { val (lu, pivots) = tensor.lu() - // todo check lu - val (p, l, u) = luPivot(lu, pivots) assertTrue { p.shape contentEquals shape } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 4de69e1ad..5c068ce83 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -3,7 +3,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.structures.toDoubleArray -import kotlin.test.Ignore +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index fa7a8fd32..10a9176dc 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -1,7 +1,9 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.test.Test +import kotlin.test.assertFalse import kotlin.test.assertTrue class TestDoubleTensorAlgebra { @@ -133,9 +135,9 @@ class TestDoubleTensorAlgebra { assertTrue(diagonal1.buffer.array() contentEquals doubleArrayOf(10.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 30.0)) - val diagonal1_offset = diagonalEmbedding(tensor1, 1, 1, 0) - assertTrue(diagonal1_offset.shape contentEquals intArrayOf(4, 4)) - assertTrue(diagonal1_offset.buffer.array() contentEquals + val diagonal1Offset = diagonalEmbedding(tensor1, 1, 1, 0) + assertTrue(diagonal1Offset.shape contentEquals intArrayOf(4, 4)) + assertTrue(diagonal1Offset.buffer.array() contentEquals doubleArrayOf(0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 30.0, 0.0)) val diagonal2 = diagonalEmbedding(tensor2, 1, 0, 2) @@ -149,7 +151,15 @@ class TestDoubleTensorAlgebra { } @Test - fun testContentEqual() = DoubleTensorAlgebra { - //TODO() + fun testEq() = DoubleTensorAlgebra { + val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + val tensor3 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) + val tensor4 = fromArray(intArrayOf(6, 1), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + + assertTrue(tensor1 eq tensor1) + assertTrue(tensor1 eq tensor2) + assertFalse(tensor1.eq(tensor3)) + } } \ No newline at end of file From 287e2aeba2ba274508f42f1ab0a839ed69861bc1 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 23 Apr 2021 14:22:52 +0100 Subject: [PATCH 237/393] div operator --- .../kmath/tensors/api/TensorPartialDivisionAlgebra.kt | 1 + .../kmath/tensors/core/algebras/DoubleTensorAlgebra.kt | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt index 075e86e61..4dab3dd07 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt @@ -8,6 +8,7 @@ package space.kscience.kmath.tensors.api // https://proofwiki.org/wiki/Definition:Division_Algebra public interface TensorPartialDivisionAlgebra : TensorAlgebra { + public operator fun T.div(other: TensorStructure): TensorStructure public operator fun TensorStructure.div(value: T): TensorStructure public operator fun TensorStructure.div(other: TensorStructure): TensorStructure public operator fun TensorStructure.divAssign(value: T) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 651db2c21..b61a484d0 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -178,13 +178,15 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } } - override fun TensorStructure.div(value: Double): DoubleTensor { - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[tensor.bufferStart + i] / value + override fun Double.div(other: TensorStructure): DoubleTensor { + val resBuffer = DoubleArray(other.tensor.numElements) { i -> + other.tensor.buffer.array()[other.tensor.bufferStart + i] / this } - return DoubleTensor(tensor.shape, resBuffer) + return DoubleTensor(other.shape, resBuffer) } + override fun TensorStructure.div(value: Double): DoubleTensor = value / tensor + override fun TensorStructure.div(other: TensorStructure): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> From 077c2b4e3b7168a297f5518876dca8ca9a390578 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov <38042667+CommanderTvis@users.noreply.github.com> Date: Fri, 23 Apr 2021 08:49:01 +0700 Subject: [PATCH 238/393] Update README.md in kmath-ast --- kmath-ast/README.md | 5 +++-- kmath-ast/docs/README-TEMPLATE.md | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/kmath-ast/README.md b/kmath-ast/README.md index eedba16fa..1ee78956e 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -50,7 +50,7 @@ For example, the following builder: MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -… leads to generation of bytecode, which can be decompiled to the following Java class: +... leads to generation of bytecode, which can be decompiled to the following Java class: ```java package space.kscience.kmath.asm.generated; @@ -97,6 +97,7 @@ var executable = function (constants, arguments) { }; ``` +JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported. ```kotlin import space.kscience.kmath.wasm.* @@ -104,7 +105,7 @@ import space.kscience.kmath.wasm.* MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -An example of emitted WASM IR in the form of WAT: +An example of emitted Wasm IR in the form of WAT: ```lisp (func $executable (param $0 f64) (result f64) diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index b38311ea1..1ecf477ef 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -19,7 +19,7 @@ For example, the following builder: MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -… leads to generation of bytecode, which can be decompiled to the following Java class: +... leads to generation of bytecode, which can be decompiled to the following Java class: ```java package space.kscience.kmath.asm.generated; @@ -66,6 +66,7 @@ var executable = function (constants, arguments) { }; ``` +JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported. ```kotlin import space.kscience.kmath.wasm.* @@ -73,7 +74,7 @@ import space.kscience.kmath.wasm.* MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` -An example of emitted WASM IR in the form of WAT: +An example of emitted Wasm IR in the form of WAT: ```lisp (func \$executable (param \$0 f64) (result f64) From 4f593aec63cd931ebe2d254baf6cee0ef3ca342c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sat, 24 Apr 2021 18:53:21 +0100 Subject: [PATCH 239/393] Buffer mini-protocol --- kmath-core/api/kmath-core.api | 8 ++++- .../space/kscience/kmath/nd/BufferND.kt | 35 ++++++++++++++++++- .../kmath/tensors/core/BufferedTensor.kt | 2 ++ .../kscience/kmath/tensors/core/utils.kt | 23 +++--------- .../kmath/tensors/core/TestDoubleTensor.kt | 34 ++++++++++++++++++ 5 files changed, 81 insertions(+), 21 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 38cfbd58d..41b85b3bb 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -748,7 +748,7 @@ public final class space/kscience/kmath/nd/BufferAlgebraNDKt { public static final fun ring (Lspace/kscience/kmath/nd/AlgebraND$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;[I)Lspace/kscience/kmath/nd/BufferedRingND; } -public final class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/StructureND { +public class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/StructureND { public fun (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/Buffer;)V public fun elements ()Lkotlin/sequences/Sequence; public fun get ([I)Ljava/lang/Object; @@ -876,6 +876,12 @@ public abstract interface class space/kscience/kmath/nd/GroupND : space/kscience public final class space/kscience/kmath/nd/GroupND$Companion { } +public final class space/kscience/kmath/nd/MutableBufferND : space/kscience/kmath/nd/BufferND, space/kscience/kmath/nd/MutableStructureND { + public fun (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/MutableBuffer;)V + public final fun getMutableBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun set ([ILjava/lang/Object;)V +} + public abstract interface class space/kscience/kmath/nd/MutableStructure1D : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/Structure1D, space/kscience/kmath/structures/MutableBuffer { public fun set ([ILjava/lang/Object;)V } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt index 23d961a7e..1f608f478 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt @@ -7,6 +7,8 @@ package space.kscience.kmath.nd import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory +import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.MutableBufferFactory /** * Represents [StructureND] over [Buffer]. @@ -15,7 +17,7 @@ import space.kscience.kmath.structures.BufferFactory * @param strides The strides to access elements of [Buffer] by linear indices. * @param buffer The underlying buffer. */ -public class BufferND( +public open class BufferND( public val strides: Strides, public val buffer: Buffer, ) : StructureND { @@ -50,4 +52,35 @@ public inline fun StructureND.mapToBuffer( val strides = DefaultStrides(shape) BufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) } +} + +/** + * Represents [MutableStructureND] over [MutableBuffer]. + * + * @param T the type of items. + * @param strides The strides to access elements of [MutableBuffer] by linear indices. + * @param mutableBuffer The underlying buffer. + */ +public class MutableBufferND( + strides: Strides, + public val mutableBuffer: MutableBuffer, +) : MutableStructureND, BufferND(strides, mutableBuffer) { + override fun set(index: IntArray, value: T) { + mutableBuffer[strides.offset(index)] = value + } +} + +/** + * Transform structure to a new structure using provided [MutableBufferFactory] and optimizing if argument is [MutableBufferND] + */ +public inline fun MutableStructureND.mapToMutableBuffer( + factory: MutableBufferFactory = MutableBuffer.Companion::auto, + crossinline transform: (T) -> R, +): MutableBufferND { + return if (this is MutableBufferND) + MutableBufferND(this.strides, factory.invoke(strides.linearSize) { transform(mutableBuffer[it]) }) + else { + val strides = DefaultStrides(shape) + MutableBufferND(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) }) + } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 5c0d9c4ea..1e9b458b1 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.api.TensorStructure import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure @@ -60,6 +61,7 @@ internal inline fun BufferedTensor.asTensor(): DoubleTensor = DoubleTens internal inline fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { is BufferedTensor -> this + is MutableBufferND -> BufferedTensor(this.shape, this.mutableBuffer, 0) else -> BufferedTensor(this.shape, this.elements().map{ it.second }.toMutableList().asMutableBuffer(), 0) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index d7d006e42..89e9d0d96 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -7,35 +7,20 @@ import space.kscience.kmath.structures.* import kotlin.math.* /** - * Returns a reference to [IntArray] containing all of the elements of this [Buffer]. + * Returns a reference to [IntArray] containing all of the elements of this [Buffer] or copy the data. */ internal fun Buffer.array(): IntArray = when (this) { is IntBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to IntArray") + else -> this.toIntArray() } -/** - * Returns a reference to [LongArray] containing all of the elements of this [Buffer]. - */ -internal fun Buffer.array(): LongArray = when (this) { - is LongBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to LongArray") -} /** - * Returns a reference to [FloatArray] containing all of the elements of this [Buffer]. - */ -internal fun Buffer.array(): FloatArray = when (this) { - is FloatBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to FloatArray") -} - -/** - * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer]. + * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer] or copy the data. */ internal fun Buffer.array(): DoubleArray = when (this) { is DoubleBuffer -> array - else -> throw RuntimeException("Failed to cast Buffer to DoubleArray") + else -> this.toDoubleArray() } internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 5c068ce83..f9d15c216 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,7 +1,11 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.DefaultStrides +import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.asMutableBuffer import space.kscience.kmath.structures.toDoubleArray import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.test.Test @@ -47,4 +51,34 @@ class TestDoubleTensor { assertEquals(secondRow[1], secondColumn[1]) } } + + @Test + fun bufferProtocol() { + + // create buffers + val doubleBuffer = DoubleBuffer(doubleArrayOf(1.0,2.0,3.0)) + val doubleList = MutableList(3, doubleBuffer::get) + + // create ND buffers + val ndBuffer = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleBuffer) + val ndList = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleList.asMutableBuffer()) + + // map to tensors + val bufferedTensorBuffer = ndBuffer.toBufferedTensor() // strides are flipped + val tensorBuffer = bufferedTensorBuffer.asTensor() // no data copied + + val bufferedTensorList = ndList.toBufferedTensor() // strides are flipped + val tensorList = bufferedTensorList.asTensor() // data copied + + tensorBuffer[intArrayOf(0)] = 55.9 + assertEquals(ndBuffer[intArrayOf(0)], 55.9) + assertEquals(doubleBuffer[0], 55.9) + + tensorList[intArrayOf(0)] = 55.9 + assertEquals(ndList[intArrayOf(0)], 1.0) + assertEquals(doubleList[0], 1.0) + + ndList[intArrayOf(0)] = 55.9 + assertEquals(doubleList[0], 55.9) + } } \ No newline at end of file From 2c001cb1b32f25dc4c245bc32b4046bf78e85cca Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Mon, 26 Apr 2021 17:07:49 +0300 Subject: [PATCH 240/393] fix div + simple tests --- .../tensors/core/algebras/DoubleTensorAlgebra.kt | 9 +++++++-- .../kmath/tensors/core/TestDoubleTensorAlgebra.kt | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index b61a484d0..7414a4469 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -180,12 +180,17 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun Double.div(other: TensorStructure): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> - other.tensor.buffer.array()[other.tensor.bufferStart + i] / this + this / other.tensor.buffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } - override fun TensorStructure.div(value: Double): DoubleTensor = value / tensor + override fun TensorStructure.div(value: Double): DoubleTensor { + val resBuffer = DoubleArray(tensor.numElements) { i -> + tensor.buffer.array()[tensor.bufferStart + i] / value + } + return DoubleTensor(shape, resBuffer) + } override fun TensorStructure.div(other: TensorStructure): DoubleTensor { checkShapesCompatible(tensor, other) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 10a9176dc..1333a7a1f 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -15,6 +15,20 @@ class TestDoubleTensorAlgebra { assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0, 12.0)) } + @Test + fun doubleDiv() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0)) + val res = 2.0/tensor + assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 0.5)) + } + + @Test + fun divDouble() = DoubleTensorAlgebra { + val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0)) + val res = tensor / 2.5 + assertTrue(res.buffer.array() contentEquals doubleArrayOf(4.0, 2.0)) + } + @Test fun transpose1x1() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1), doubleArrayOf(0.0)) From 30ca333c040b09ca65d528b052fa27492161654a Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Mon, 26 Apr 2021 17:27:50 +0300 Subject: [PATCH 241/393] OLS/SVD example --- examples/build.gradle.kts | 1 + .../kscience/kmath/tensors/OLSWithSVD.kt | 68 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 56feee9dc..a4eabc2b8 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { implementation(project(":kmath-dimensions")) implementation(project(":kmath-ejml")) implementation(project(":kmath-nd4j")) + implementation(project(":kmath-tensors")) implementation(project(":kmath-for-real")) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt new file mode 100644 index 000000000..063a1d1c4 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -0,0 +1,68 @@ +/* + * 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.tensors + +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra + +// OLS estimator using SVD + +fun main() { + //seed for random + val randSeed = 100500L + + // work in context with linear operations + DoubleLinearOpsTensorAlgebra { + // take coefficient vector from normal distribution + val alpha = randNormal( + intArrayOf(5), + randSeed + ) + fromArray( + intArrayOf(5), + doubleArrayOf(1.0, 2.5, 3.4, 5.0, 10.1) + ) + + println("Real alpha:\n" + + "$alpha") + + // also take sample of size 20 from normal distribution for x TODO rename + val x = randNormal( + intArrayOf(20, 5), + randSeed + ) + + // calculate y and add gaussian noise (N(0, 0.05)) TODO rename + val y = x dot alpha + y += y.randNormalLike(randSeed) * 0.05 + + // now restore the coefficient vector with OSL estimator with SVD + val (u, singValues, v) = x.svd() + + // we have to make sure the singular values of the matrix are not close to zero + println("Singular values:\n" + + "$singValues") + // TODO something with Boolean tensors + + // inverse Sigma matrix can be restored from singular values with diagonalEmbedding function + val sigma = diagonalEmbedding(1.0/singValues) + + val alphaOLS = v dot sigma dot u.transpose() dot y + println("Estimated alpha:\n" + + "$alphaOLS") + + // figure out MSE of approximation + fun mse(yTrue: DoubleTensor, yPred: DoubleTensor): Double = DoubleAnalyticTensorAlgebra{ + require(yTrue.shape.size == 1) + require(yTrue.shape contentEquals yPred.shape) + + val diff = yTrue - yPred + diff.dot(diff).sqrt().value() + } + + println("MSE: ${mse(alpha, alphaOLS)}") + } +} \ No newline at end of file From c2db3a23e1e6a14463d3dadac6d279ccabb49272 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 26 Apr 2021 16:24:26 +0100 Subject: [PATCH 242/393] Feedback for SVD --- .../space/kscience/kmath/tensors/OLSWithSVD.kt | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 063a1d1c4..a9b154017 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -9,6 +9,8 @@ import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra +import kotlin.math.abs + // OLS estimator using SVD fun main() { @@ -26,8 +28,7 @@ fun main() { doubleArrayOf(1.0, 2.5, 3.4, 5.0, 10.1) ) - println("Real alpha:\n" + - "$alpha") + println("Real alpha:\n$alpha") // also take sample of size 20 from normal distribution for x TODO rename val x = randNormal( @@ -35,20 +36,22 @@ fun main() { randSeed ) - // calculate y and add gaussian noise (N(0, 0.05)) TODO rename + // calculate y and add gaussian noise (N(0, 0.05)) + // TODO: please add an intercept: Y = beta * X + alpha + N(0,0.5) val y = x dot alpha y += y.randNormalLike(randSeed) * 0.05 // now restore the coefficient vector with OSL estimator with SVD + // TODO: you need to change accordingly [X 1] [alpha beta] = Y + // TODO: inverting [X 1] via SVD val (u, singValues, v) = x.svd() // we have to make sure the singular values of the matrix are not close to zero - println("Singular values:\n" + - "$singValues") - // TODO something with Boolean tensors + println("Singular values:\n$singValues") + // inverse Sigma matrix can be restored from singular values with diagonalEmbedding function - val sigma = diagonalEmbedding(1.0/singValues) + val sigma = diagonalEmbedding(singValues.map{ x -> if (abs(x) < 1e-3) 0.0 else 1.0/x }) val alphaOLS = v dot sigma dot u.transpose() dot y println("Estimated alpha:\n" + From 23ea4a95a151e8ce1a70566a4ede3c7d343e5caa Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Tue, 27 Apr 2021 19:01:54 +0100 Subject: [PATCH 243/393] Fixed strides flipping --- .../kmath/tensors/core/BufferedTensor.kt | 23 +++++--- .../kmath/tensors/core/TestDoubleTensor.kt | 58 ++++++++++--------- 2 files changed, 45 insertions(+), 36 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 1e9b458b1..6e1cab11a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -37,9 +37,8 @@ public class IntTensor internal constructor( shape: IntArray, buffer: IntArray, offset: Int = 0 -) : BufferedTensor(shape, IntBuffer(buffer), offset) -{ - internal constructor(bufferedTensor: BufferedTensor): +) : BufferedTensor(shape, IntBuffer(buffer), offset) { + internal constructor(bufferedTensor: BufferedTensor) : this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) } @@ -47,9 +46,8 @@ public class DoubleTensor internal constructor( shape: IntArray, buffer: DoubleArray, offset: Int = 0 -) : BufferedTensor(shape, DoubleBuffer(buffer), offset) -{ - internal constructor(bufferedTensor: BufferedTensor): +) : BufferedTensor(shape, DoubleBuffer(buffer), offset) { + internal constructor(bufferedTensor: BufferedTensor) : this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) override fun toString(): String = toPrettyString() @@ -59,10 +57,17 @@ public class DoubleTensor internal constructor( internal inline fun BufferedTensor.asTensor(): IntTensor = IntTensor(this) internal inline fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this) +internal inline fun TensorStructure.copyToBufferedTensor(): BufferedTensor = + BufferedTensor( + this.shape, + TensorLinearStructure(this.shape).indices().map(this::get).toMutableList().asMutableBuffer(), 0 + ) + internal inline fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { is BufferedTensor -> this - is MutableBufferND -> BufferedTensor(this.shape, this.mutableBuffer, 0) - else -> BufferedTensor(this.shape, this.elements().map{ it.second }.toMutableList().asMutableBuffer(), 0) + is MutableBufferND -> if (this.strides.strides.toIntArray() contentEquals TensorLinearStructure(this.shape).strides) + BufferedTensor(this.shape, this.mutableBuffer, 0) else this.copyToBufferedTensor() + else -> this.copyToBufferedTensor() } internal val TensorStructure.tensor: DoubleTensor @@ -77,3 +82,5 @@ internal val TensorStructure.tensor: IntTensor else -> this.toBufferedTensor().asTensor() } +public fun TensorStructure.toTypedTensor(): DoubleTensor = this.tensor +public fun TensorStructure.toTypedTensor(): IntTensor = this.tensor \ No newline at end of file diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index f9d15c216..7103eafaa 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -23,62 +23,64 @@ class TestDoubleTensor { @Test fun stridesTest() = DoubleTensorAlgebra { - val tensor = fromArray(intArrayOf(2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) - assertEquals(tensor[intArrayOf(0,1)], 5.8) - assertTrue(tensor.elements().map{ it.second }.toList().toDoubleArray() contentEquals tensor.buffer.toDoubleArray()) + val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) + assertEquals(tensor[intArrayOf(0, 1)], 5.8) + assertTrue( + tensor.elements().map { it.second }.toList().toDoubleArray() contentEquals tensor.buffer.toDoubleArray() + ) } @Test fun getTest() = DoubleTensorAlgebra { - val tensor = fromArray(intArrayOf(1,2,2), doubleArrayOf(3.5,5.8,58.4,2.4)) + val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) val matrix = tensor[0].as2D() - assertEquals(matrix[0,1], 5.8) + assertEquals(matrix[0, 1], 5.8) val vector = tensor[0][1].as1D() assertEquals(vector[0], 58.4) - matrix[0,1] = 77.89 - assertEquals(tensor[intArrayOf(0,0,1)], 77.89) + matrix[0, 1] = 77.89 + assertEquals(tensor[intArrayOf(0, 0, 1)], 77.89) vector[0] = 109.56 - assertEquals(tensor[intArrayOf(0,1,0)], 109.56) + assertEquals(tensor[intArrayOf(0, 1, 0)], 109.56) tensor.matrixSequence().forEach { val a = it.asTensor() val secondRow = a[1].as1D() - val secondColumn = a.transpose(0,1)[1].as1D() + val secondColumn = a.transpose(0, 1)[1].as1D() assertEquals(secondColumn[0], 77.89) assertEquals(secondRow[1], secondColumn[1]) } } @Test - fun bufferProtocol() { + fun noBufferProtocol() { - // create buffers - val doubleBuffer = DoubleBuffer(doubleArrayOf(1.0,2.0,3.0)) - val doubleList = MutableList(3, doubleBuffer::get) + // create buffer + val doubleArray = DoubleBuffer(doubleArrayOf(1.0, 2.0, 3.0)) - // create ND buffers - val ndBuffer = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleBuffer) - val ndList = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleList.asMutableBuffer()) + // create ND buffers, no data is copied + val ndArray = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleArray) // map to tensors - val bufferedTensorBuffer = ndBuffer.toBufferedTensor() // strides are flipped - val tensorBuffer = bufferedTensorBuffer.asTensor() // no data copied + val bufferedTensorArray = ndArray.toBufferedTensor() // strides are flipped so data copied + val tensorArray = bufferedTensorArray.asTensor() // data not contiguous so copied again - val bufferedTensorList = ndList.toBufferedTensor() // strides are flipped - val tensorList = bufferedTensorList.asTensor() // data copied + val tensorArrayPublic = ndArray.toTypedTensor() // public API, data copied twice + val sharedTensorArray = tensorArrayPublic.toTypedTensor() // no data copied by matching type - tensorBuffer[intArrayOf(0)] = 55.9 - assertEquals(ndBuffer[intArrayOf(0)], 55.9) - assertEquals(doubleBuffer[0], 55.9) + assertTrue(tensorArray.buffer.array() contentEquals sharedTensorArray.buffer.array()) - tensorList[intArrayOf(0)] = 55.9 - assertEquals(ndList[intArrayOf(0)], 1.0) - assertEquals(doubleList[0], 1.0) + tensorArray[intArrayOf(0)] = 55.9 + assertEquals(tensorArrayPublic[intArrayOf(0)], 1.0) + + tensorArrayPublic[intArrayOf(0)] = 55.9 + assertEquals(sharedTensorArray[intArrayOf(0)], 55.9) + assertEquals(bufferedTensorArray[intArrayOf(0)], 1.0) + + bufferedTensorArray[intArrayOf(0)] = 55.9 + assertEquals(ndArray[intArrayOf(0)], 1.0) - ndList[intArrayOf(0)] = 55.9 - assertEquals(doubleList[0], 55.9) } } \ No newline at end of file From e3f7b7a5fa560d4084a16a611b0266576d1e5728 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 28 Apr 2021 10:25:03 +0700 Subject: [PATCH 244/393] Promote kmath-ast as experimental, mark AST Rendering and WASM with @UnstableKMathAPI --- kmath-ast/build.gradle.kts | 6 +- .../kotlin/space/kscience/kmath/ast/parser.kt | 1 - .../ast/rendering/LatexSyntaxRenderer.kt | 3 + .../ast/rendering/MathMLSyntaxRenderer.kt | 5 +- .../kmath/ast/rendering/MathRenderer.kt | 4 + .../kmath/ast/rendering/MathSyntax.kt | 25 ++ .../kmath/ast/rendering/SyntaxRenderer.kt | 4 + .../kscience/kmath/ast/rendering/features.kt | 280 ++++++++++++------ .../kscience/kmath/ast/rendering/stages.kt | 4 + .../kmath/ast/ParserPrecedenceTest.kt | 1 - .../kscience/kmath/ast/rendering/TestUtils.kt | 6 +- .../nonDeclarations.WebAssembly.kt | 3 +- .../kmath/wasm/internal/WasmBuilder.kt | 2 +- .../kotlin/space/kscience/kmath/wasm/wasm.kt | 9 + .../kscience/kmath/asm/internal/AsmBuilder.kt | 4 +- .../kmath/asm/internal/codegenUtils.kt | 2 +- 16 files changed, 259 insertions(+), 100 deletions(-) diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index b4a0b28ac..508374d82 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -18,6 +18,10 @@ kotlin.js { } kotlin.sourceSets { + filter { it.name.contains("test", true) } + .map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings) + .forEach { it.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") } + commonMain { dependencies { api("com.github.h0tk3y.betterParse:better-parse:0.4.2") @@ -54,7 +58,7 @@ tasks.dokkaHtml { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt index d2e92c37f..246625d29 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt @@ -29,7 +29,6 @@ import space.kscience.kmath.operations.RingOperations * @author Iaroslav Postovalov */ public object ArithmeticsEvaluator : Grammar() { - // TODO replace with "...".toRegex() when better-parse 0.4.1 is released private val num: Token by regexToken("[\\d.]+(?:[eE][-+]?\\d+)?".toRegex()) private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*".toRegex()) private val lpar: Token by literalToken("(") diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt index 1c82bd6e7..5909f1f9d 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -5,6 +5,8 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI + /** * [SyntaxRenderer] implementation for LaTeX. * @@ -23,6 +25,7 @@ package space.kscience.kmath.ast.rendering * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object LatexSyntaxRenderer : SyntaxRenderer { public override fun render(node: MathSyntax, output: Appendable): Unit = output.run { fun render(syntax: MathSyntax) = render(syntax, output) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index decd4ba46..517ec0dc9 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -5,6 +5,8 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI + /** * [SyntaxRenderer] implementation for MathML. * @@ -12,9 +14,10 @@ package space.kscience.kmath.ast.rendering * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object MathMLSyntaxRenderer : SyntaxRenderer { public override fun render(node: MathSyntax, output: Appendable) { - output.append("") + output.append("") render0(node, output) output.append("") } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index 9df2c54dd..6b22ac519 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -6,12 +6,14 @@ package space.kscience.kmath.ast.rendering import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.UnstableKMathAPI /** * Renders [MST] to [MathSyntax]. * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun interface MathRenderer { /** * Renders [MST] to [MathSyntax]. @@ -25,6 +27,7 @@ public fun interface MathRenderer { * @property features The applied features. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public open class FeaturedMathRenderer(public val features: List) : MathRenderer { public override fun render(mst: MST): MathSyntax { for (feature in features) feature.render(this, mst)?.let { return it } @@ -48,6 +51,7 @@ public open class FeaturedMathRenderer(public val features: List) * @property stages The applied stages. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public open class FeaturedMathRendererWithPostProcess( features: List, public val stages: List, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt index 6a46bf535..3c023e342 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -5,11 +5,14 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI + /** * Mathematical typography syntax node. * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class MathSyntax { /** * The parent node of this syntax node. @@ -22,6 +25,7 @@ public sealed class MathSyntax { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class TerminalSyntax : MathSyntax() /** @@ -29,6 +33,7 @@ public sealed class TerminalSyntax : MathSyntax() * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class OperationSyntax : MathSyntax() { /** * The operation token. @@ -41,6 +46,7 @@ public sealed class OperationSyntax : MathSyntax() { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class UnarySyntax : OperationSyntax() { /** * The operand of this node. @@ -53,6 +59,7 @@ public sealed class UnarySyntax : OperationSyntax() { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public sealed class BinarySyntax : OperationSyntax() { /** * The left-hand side operand. @@ -71,6 +78,7 @@ public sealed class BinarySyntax : OperationSyntax() { * @property string The digits of number. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class NumberSyntax(public var string: String) : TerminalSyntax() /** @@ -79,6 +87,7 @@ public data class NumberSyntax(public var string: String) : TerminalSyntax() * @property string The symbol. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class SymbolSyntax(public var string: String) : TerminalSyntax() /** @@ -89,6 +98,7 @@ public data class SymbolSyntax(public var string: String) : TerminalSyntax() * @see UnaryOperatorSyntax * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class OperatorNameSyntax(public var name: String) : TerminalSyntax() /** @@ -97,6 +107,7 @@ public data class OperatorNameSyntax(public var name: String) : TerminalSyntax() * @property kind The kind of symbol. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() { /** * The kind of symbol. @@ -121,6 +132,7 @@ public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() * @property parentheses Whether the operand should be wrapped with parentheses. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class OperandSyntax( public val operand: MathSyntax, public var parentheses: Boolean, @@ -136,6 +148,7 @@ public data class OperandSyntax( * @property prefix The prefix. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class UnaryOperatorSyntax( public override val operation: String, public var prefix: MathSyntax, @@ -151,6 +164,7 @@ public data class UnaryOperatorSyntax( * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class UnaryPlusSyntax( public override val operation: String, public override val operand: OperandSyntax, @@ -165,6 +179,7 @@ public data class UnaryPlusSyntax( * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class UnaryMinusSyntax( public override val operation: String, public override val operand: OperandSyntax, @@ -180,6 +195,7 @@ public data class UnaryMinusSyntax( * @property operand The radicand. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class RadicalSyntax( public override val operation: String, public override val operand: MathSyntax, @@ -197,6 +213,7 @@ public data class RadicalSyntax( * (*ex*). * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class ExponentSyntax( public override val operation: String, public override val operand: OperandSyntax, @@ -214,6 +231,7 @@ public data class ExponentSyntax( * @property right The superscript. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class SuperscriptSyntax( public override val operation: String, public override val left: MathSyntax, @@ -232,6 +250,7 @@ public data class SuperscriptSyntax( * @property right The subscript. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class SubscriptSyntax( public override val operation: String, public override val left: MathSyntax, @@ -249,6 +268,7 @@ public data class SubscriptSyntax( * @property prefix The prefix. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class BinaryOperatorSyntax( public override val operation: String, public var prefix: MathSyntax, @@ -268,6 +288,7 @@ public data class BinaryOperatorSyntax( * @param right The addend. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class BinaryPlusSyntax( public override val operation: String, public override val left: OperandSyntax, @@ -286,6 +307,7 @@ public data class BinaryPlusSyntax( * @param right The subtrahend. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class BinaryMinusSyntax( public override val operation: String, public override val left: OperandSyntax, @@ -304,6 +326,7 @@ public data class BinaryMinusSyntax( * @property right The denominator. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class FractionSyntax( public override val operation: String, public override val left: MathSyntax, @@ -322,6 +345,7 @@ public data class FractionSyntax( * @property right The radicand. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class RadicalWithIndexSyntax( public override val operation: String, public override val left: MathSyntax, @@ -341,6 +365,7 @@ public data class RadicalWithIndexSyntax( * @property times whether the times (×) symbol should be used. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public data class MultiplicationSyntax( public override val operation: String, public override val left: OperandSyntax, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt index 7fa91e158..fb2b3b66f 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt @@ -5,12 +5,15 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI + /** * Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should * involve traversal of MathSyntax with handling each its subtype. * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun interface SyntaxRenderer { /** * Renders the [MathSyntax] to [output]. @@ -23,6 +26,7 @@ public fun interface SyntaxRenderer { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun SyntaxRenderer.renderWithStringBuilder(node: MathSyntax): String { val sb = StringBuilder() render(node, sb) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index c09282bb6..c1b513345 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -7,6 +7,7 @@ package space.kscience.kmath.ast.rendering import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import kotlin.reflect.KClass @@ -15,11 +16,12 @@ import kotlin.reflect.KClass * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object PrintSymbolic : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Symbolic) return null - return SymbolSyntax(string = node.value) - } + public override fun render(renderer: FeaturedMathRenderer, node: MST): SymbolSyntax? = + if (node !is MST.Symbolic) null + else + SymbolSyntax(string = node.value) } /** @@ -27,25 +29,25 @@ public object PrintSymbolic : RenderFeature { * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object PrintNumeric : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Numeric) return null - return NumberSyntax(string = node.value.toString()) - } + public override fun render(renderer: FeaturedMathRenderer, node: MST): NumberSyntax? = if (node !is MST.Numeric) + null + else + NumberSyntax(string = node.value.toString()) } -private fun printSignedNumberString(s: String): MathSyntax { - if (s.startsWith('-')) - return UnaryMinusSyntax( - operation = GroupOperations.MINUS_OPERATION, - operand = OperandSyntax( - operand = NumberSyntax(string = s.removePrefix("-")), - parentheses = true, - ), - ) - - return NumberSyntax(string = s) -} +@UnstableKMathAPI +private fun printSignedNumberString(s: String): MathSyntax = if (s.startsWith('-')) + UnaryMinusSyntax( + operation = GroupOperations.MINUS_OPERATION, + operand = OperandSyntax( + operand = NumberSyntax(string = s.removePrefix("-")), + parentheses = true, + ), + ) +else + NumberSyntax(string = s) /** * Special printing for numeric types which are printed in form of @@ -53,9 +55,11 @@ private fun printSignedNumberString(s: String): MathSyntax { * * @property types The suitable types. */ +@UnstableKMathAPI public class PrettyPrintFloats(public val types: Set>) : RenderFeature { public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { if (node !is MST.Numeric || node.value::class !in types) return null + val toString = when (val v = node.value) { is Float -> v.multiplatformToString() is Double -> v.multiplatformToString() @@ -110,11 +114,13 @@ public class PrettyPrintFloats(public val types: Set>) : Rend * * @property types The suitable types. */ +@UnstableKMathAPI public class PrettyPrintIntegers(public val types: Set>) : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Numeric || node.value::class !in types) return null - return printSignedNumberString(node.value.toString()) - } + public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? = + if (node !is MST.Numeric || node.value::class !in types) + null + else + printSignedNumberString(node.value.toString()) public companion object { /** @@ -130,11 +136,13 @@ public class PrettyPrintIntegers(public val types: Set>) : Re * * @property symbols The allowed symbols. */ +@UnstableKMathAPI public class PrettyPrintPi(public val symbols: Set) : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Symbolic || node.value !in symbols) return null - return SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI) - } + public override fun render(renderer: FeaturedMathRenderer, node: MST): SpecialSymbolSyntax? = + if (node !is MST.Symbolic || node.value !in symbols) + null + else + SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI) public companion object { /** @@ -150,16 +158,18 @@ public class PrettyPrintPi(public val symbols: Set) : RenderFeature { * * @param operations the allowed operations. If `null`, any operation is accepted. */ +@UnstableKMathAPI public abstract class Unary(public val operations: Collection?) : RenderFeature { /** - * The actual render function. + * The actual render function specialized for [MST.Unary]. */ - protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax? + protected abstract fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax? - public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { - if (node !is MST.Unary || operations != null && node.operation !in operations) return null - return render0(renderer, node) - } + public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? = + if (node !is MST.Unary || operations != null && node.operation !in operations) + null + else + renderUnary(renderer, node) } /** @@ -168,164 +178,258 @@ public abstract class Unary(public val operations: Collection?) : Render * * @property operations the allowed operations. If `null`, any operation is accepted. */ +@UnstableKMathAPI public abstract class Binary(public val operations: Collection?) : RenderFeature { /** - * The actual render function. + * The actual render function specialized for [MST.Binary]. */ - protected abstract fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax? + protected abstract fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax? public final override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { if (node !is MST.Binary || operations != null && node.operation !in operations) return null - return render0(renderer, node) + return renderBinary(renderer, node) } } +/** + * Handles binary nodes by producing [BinaryPlusSyntax]. + */ +@UnstableKMathAPI public class BinaryPlus(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryPlusSyntax( - operation = node.operation, - left = OperandSyntax(parent.render(node.left), true), - right = OperandSyntax(parent.render(node.right), true), - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryPlusSyntax = + BinaryPlusSyntax( + operation = node.operation, + left = OperandSyntax(parent.render(node.left), true), + right = OperandSyntax(parent.render(node.right), true), + ) public companion object { + /** + * The default instance configured with [GroupOperations.PLUS_OPERATION]. + */ public val Default: BinaryPlus = BinaryPlus(setOf(GroupOperations.PLUS_OPERATION)) } } +/** + * Handles binary nodes by producing [BinaryMinusSyntax]. + */ +@UnstableKMathAPI public class BinaryMinus(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryMinusSyntax( - operation = node.operation, - left = OperandSyntax(operand = parent.render(node.left), parentheses = true), - right = OperandSyntax(operand = parent.render(node.right), parentheses = true), - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryMinusSyntax = + BinaryMinusSyntax( + operation = node.operation, + left = OperandSyntax(operand = parent.render(node.left), parentheses = true), + right = OperandSyntax(operand = parent.render(node.right), parentheses = true), + ) public companion object { + /** + * The default instance configured with [GroupOperations.MINUS_OPERATION]. + */ public val Default: BinaryMinus = BinaryMinus(setOf(GroupOperations.MINUS_OPERATION)) } } +/** + * Handles unary nodes by producing [UnaryPlusSyntax]. + */ +@UnstableKMathAPI public class UnaryPlus(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax( + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryPlusSyntax = UnaryPlusSyntax( operation = node.operation, operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), ) public companion object { + /** + * The default instance configured with [GroupOperations.PLUS_OPERATION]. + */ public val Default: UnaryPlus = UnaryPlus(setOf(GroupOperations.PLUS_OPERATION)) } } +/** + * Handles binary nodes by producing [UnaryMinusSyntax]. + */ +@UnstableKMathAPI public class UnaryMinus(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax( + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryMinusSyntax = UnaryMinusSyntax( operation = node.operation, operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), ) public companion object { + /** + * The default instance configured with [GroupOperations.MINUS_OPERATION]. + */ public val Default: UnaryMinus = UnaryMinus(setOf(GroupOperations.MINUS_OPERATION)) } } +/** + * Handles binary nodes by producing [FractionSyntax]. + */ +@UnstableKMathAPI public class Fraction(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax( + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = FractionSyntax( operation = node.operation, left = parent.render(node.left), right = parent.render(node.right), ) public companion object { + /** + * The default instance configured with [FieldOperations.DIV_OPERATION]. + */ public val Default: Fraction = Fraction(setOf(FieldOperations.DIV_OPERATION)) } } +/** + * Handles binary nodes by producing [BinaryOperatorSyntax]. + */ +@UnstableKMathAPI public class BinaryOperator(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryOperatorSyntax( - operation = node.operation, - prefix = OperatorNameSyntax(name = node.operation), - left = parent.render(node.left), - right = parent.render(node.right), - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryOperatorSyntax = + BinaryOperatorSyntax( + operation = node.operation, + prefix = OperatorNameSyntax(name = node.operation), + left = parent.render(node.left), + right = parent.render(node.right), + ) public companion object { + /** + * The default instance configured with `null`. + */ public val Default: BinaryOperator = BinaryOperator(null) } } +/** + * Handles unary nodes by producing [UnaryOperatorSyntax]. + */ +@UnstableKMathAPI public class UnaryOperator(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( - operation = node.operation, - prefix = OperatorNameSyntax(node.operation), - operand = OperandSyntax(parent.render(node.value), true), - ) + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = + UnaryOperatorSyntax( + operation = node.operation, + prefix = OperatorNameSyntax(node.operation), + operand = OperandSyntax(parent.render(node.value), true), + ) public companion object { + /** + * The default instance configured with `null`. + */ public val Default: UnaryOperator = UnaryOperator(null) } } +/** + * Handles binary nodes by producing [SuperscriptSyntax]. + */ +@UnstableKMathAPI public class Power(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = SuperscriptSyntax( - operation = node.operation, - left = OperandSyntax(parent.render(node.left), true), - right = OperandSyntax(parent.render(node.right), true), - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): SuperscriptSyntax = + SuperscriptSyntax( + operation = node.operation, + left = OperandSyntax(parent.render(node.left), true), + right = OperandSyntax(parent.render(node.right), true), + ) public companion object { + /** + * The default instance configured with [PowerOperations.POW_OPERATION]. + */ public val Default: Power = Power(setOf(PowerOperations.POW_OPERATION)) } } +/** + * Handles binary nodes by producing [RadicalSyntax] with no index. + */ +@UnstableKMathAPI public class SquareRoot(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): RadicalSyntax = RadicalSyntax(operation = node.operation, operand = parent.render(node.value)) public companion object { + /** + * The default instance configured with [PowerOperations.SQRT_OPERATION]. + */ public val Default: SquareRoot = SquareRoot(setOf(PowerOperations.SQRT_OPERATION)) } } +/** + * Handles unary nodes by producing [ExponentSyntax]. + */ +@UnstableKMathAPI public class Exponent(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax( + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): ExponentSyntax = ExponentSyntax( operation = node.operation, operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), useOperatorForm = true, ) public companion object { + /** + * The default instance configured with [ExponentialOperations.EXP_OPERATION]. + */ public val Default: Exponent = Exponent(setOf(ExponentialOperations.EXP_OPERATION)) } } +/** + * Handles binary nodes by producing [MultiplicationSyntax]. + */ +@UnstableKMathAPI public class Multiplication(operations: Collection?) : Binary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = MultiplicationSyntax( - operation = node.operation, - left = OperandSyntax(operand = parent.render(node.left), parentheses = true), - right = OperandSyntax(operand = parent.render(node.right), parentheses = true), - times = true, - ) + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MultiplicationSyntax = + MultiplicationSyntax( + operation = node.operation, + left = OperandSyntax(operand = parent.render(node.left), parentheses = true), + right = OperandSyntax(operand = parent.render(node.right), parentheses = true), + times = true, + ) public companion object { - public val Default: Multiplication = Multiplication(setOf( - RingOperations.TIMES_OPERATION, - )) + /** + * The default instance configured with [RingOperations.TIMES_OPERATION]. + */ + public val Default: Multiplication = Multiplication(setOf(RingOperations.TIMES_OPERATION)) } } +/** + * Handles binary nodes by producing inverse [UnaryOperatorSyntax] (like *sin-1*) with removing the `a` + * prefix of operation ID. + */ +@UnstableKMathAPI public class InverseTrigonometricOperations(operations: Collection?) : Unary(operations) { - public override fun render0(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( - operation = node.operation, - prefix = SuperscriptSyntax( - operation = PowerOperations.POW_OPERATION, - left = OperatorNameSyntax(name = node.operation.removePrefix("a")), - right = UnaryMinusSyntax( - operation = GroupOperations.MINUS_OPERATION, - operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true), + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = + UnaryOperatorSyntax( + operation = node.operation, + prefix = SuperscriptSyntax( + operation = PowerOperations.POW_OPERATION, + left = OperatorNameSyntax(name = node.operation.removePrefix("a")), + right = UnaryMinusSyntax( + operation = GroupOperations.MINUS_OPERATION, + operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true), + ), ), - ), - operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), - ) + operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), + ) public companion object { + /** + * The default instance configured with [TrigonometricOperations.ACOS_OPERATION], + * [TrigonometricOperations.ASIN_OPERATION], [TrigonometricOperations.ATAN_OPERATION], + * [ExponentialOperations.ACOSH_OPERATION], [ExponentialOperations.ASINH_OPERATION], and + * [ExponentialOperations.ATANH_OPERATION]. + */ public val Default: InverseTrigonometricOperations = InverseTrigonometricOperations(setOf( TrigonometricOperations.ACOS_OPERATION, TrigonometricOperations.ASIN_OPERATION, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt index a08f089f1..7eb75b9ff 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.FieldOperations import space.kscience.kmath.operations.GroupOperations import space.kscience.kmath.operations.PowerOperations @@ -15,6 +16,7 @@ import space.kscience.kmath.operations.RingOperations * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage { public override fun perform(node: MathSyntax): Unit = when (node) { is NumberSyntax -> Unit @@ -88,6 +90,7 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage { private fun perform0(node: MathSyntax): Boolean { return when (node) { @@ -129,6 +132,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt * @property precedenceFunction Returns the precedence number for syntax node. Higher number is lower priority. * @author Iaroslav Postovalov */ +@UnstableKMathAPI public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) : FeaturedMathRendererWithPostProcess.PostProcessStage { public override fun perform(node: MathSyntax): Unit = when (node) { diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt index ca3a95bc8..67d77839a 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.ast -import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.evaluate import space.kscience.kmath.operations.DoubleField import kotlin.test.Test diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt index 7c9400532..bf87b6fd0 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt @@ -30,17 +30,17 @@ internal object TestUtils { ) internal fun testMathML(mst: MST, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", + expected = "$expectedMathML", actual = mathML(mst), ) internal fun testMathML(expression: String, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", + expected = "$expectedMathML", actual = mathML(expression.parseMath()), ) internal fun testMathML(expression: MathSyntax, expectedMathML: String) = assertEquals( - expected = "$expectedMathML", + expected = "$expectedMathML", actual = MathMLSyntaxRenderer.renderWithStringBuilder(expression), ) } diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt index 59733299a..c5023c384 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt @@ -3,7 +3,8 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -@file:Suppress("INTERFACE_WITH_SUPERCLASS", +@file:Suppress( + "INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS", diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt index bd2b340a0..8fd3c9fb9 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -26,7 +26,7 @@ internal sealed class WasmBuilder( val keys: MutableList = mutableListOf() lateinit var ctx: BinaryenModule - open fun visitSymbolic(mst: MST.Symbolic): ExpressionRef { + open fun visitSymbolic(mst: Symbolic): ExpressionRef { try { algebra.bindSymbol(mst.value) } catch (ignored: Throwable) { diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt index d44c4e49d..394a0567e 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt @@ -10,6 +10,7 @@ import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.invoke import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing import space.kscience.kmath.wasm.internal.DoubleWasmBuilder @@ -20,6 +21,7 @@ import space.kscience.kmath.wasm.internal.IntWasmBuilder * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun DoubleField.expression(mst: MST): Expression = DoubleWasmBuilder(mst).instance @@ -28,6 +30,7 @@ public fun DoubleField.expression(mst: MST): Expression = * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun IntRing.expression(mst: MST): Expression = IntWasmBuilder(mst).instance @@ -36,6 +39,7 @@ public fun IntRing.expression(mst: MST): Expression = * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compileToExpression(algebra: IntRing): Expression = compileWith(algebra) @@ -44,6 +48,7 @@ public fun MST.compileToExpression(algebra: IntRing): Expression = compileW * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compile(algebra: IntRing, arguments: Map): Int = compileToExpression(algebra).invoke(arguments) @@ -53,6 +58,7 @@ public fun MST.compile(algebra: IntRing, arguments: Map): Int = * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compile(algebra: IntRing, vararg arguments: Pair): Int = compileToExpression(algebra)(*arguments) @@ -61,6 +67,7 @@ public fun MST.compile(algebra: IntRing, vararg arguments: Pair): I * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compileToExpression(algebra: DoubleField): Expression = compileWith(algebra) @@ -69,6 +76,7 @@ public fun MST.compileToExpression(algebra: DoubleField): Expression = c * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compile(algebra: DoubleField, arguments: Map): Double = compileToExpression(algebra).invoke(arguments) @@ -78,5 +86,6 @@ public fun MST.compile(algebra: DoubleField, arguments: Map): Do * * @author Iaroslav Postovalov */ +@UnstableKMathAPI public fun MST.compile(algebra: DoubleField, vararg arguments: Pair): Double = compileToExpression(algebra).invoke(*arguments) diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt index bdd8f52b6..39ebf049d 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt @@ -342,8 +342,8 @@ internal class AsmBuilder( val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("space/kscience/kmath/asm/internal/MapIntrinsics") } /** - * ASM Type for [kscience.kmath.expressions.Symbol]. + * ASM Type for [space.kscience.kmath.misc.Symbol]. */ - val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Symbol") } + val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/misc/Symbol") } } } diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt index 560780f99..cfac59847 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt @@ -52,7 +52,7 @@ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.( * * @author Iaroslav Postovalov */ -internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) } +internal fun MethodVisitor.label(): Label = Label().also(::visitLabel) /** * Creates a class name for [Expression] subclassed to implement [mst] provided. From b65a673173e6b1cd209fa355349bf9b90f718887 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 28 Apr 2021 14:16:57 +0100 Subject: [PATCH 245/393] Fix format for 0.0 --- .../kotlin/space/kscience/kmath/tensors/core/utils.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 89e9d0d96..cb23dbdd6 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -47,17 +47,17 @@ internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexF internal inline fun format(value: Double, digits: Int = 4): String { val ten = 10.0 - val approxOrder = ceil(log10(abs(value))).toInt() + val approxOrder = if(value == 0.0) 0 else ceil(log10(abs(value))).toInt() val order = if( ((value % ten) == 0.0) or (value == 1.0) or ((1/value) % ten == 0.0)) approxOrder else approxOrder - 1 - val lead = value / ten.pow(order) val leadDisplay = round(lead*ten.pow(digits)) / ten.pow(digits) val orderDisplay = if(order == 0) "" else if(order > 0) "E+$order" else "E$order" val valueDisplay = "$leadDisplay$orderDisplay" val res = if(value < 0.0) valueDisplay else " $valueDisplay" + val fLength = digits + 6 val endSpace = " ".repeat(fLength - res.length) return "$res$endSpace" From a0e9180db6da06c2cdac36a25c4b44d951945850 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 28 Apr 2021 18:18:57 +0300 Subject: [PATCH 246/393] example with LUP --- .../tensors/LinearSystemSolvingWithLUP.kt | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt new file mode 100644 index 000000000..526b6781f --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -0,0 +1,97 @@ +/* + * 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.tensors + +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra + +// solving linear system with LUP decomposition + +fun main () { + + // work in context with linear operations + DoubleLinearOpsTensorAlgebra { + + // set true value of x + val trueX = fromArray( + intArrayOf(4), + doubleArrayOf(-2.0, 1.5, 6.8, -2.4) + ) + + // and A matrix + val a = fromArray( + intArrayOf(4, 4), + doubleArrayOf( + 0.5, 10.5, 4.5, 1.0, + 8.5, 0.9, 12.8, 0.1, + 5.56, 9.19, 7.62, 5.45, + 1.0, 2.0, -3.0, -2.5 + ) + ) + + // calculate y value + val b = a dot trueX + + // check out A and b + println("A:\n$a") + println("b:\n$b") + + // solve `Ax = b` system using LUP decomposition + + // get P, L, U such that PA = LU + val (lu, pivots) = a.lu() + val (p, l, u) = luPivot(lu, pivots) + + // check that P is permutation matrix + println("P:\n$p") + // L is lower triangular matrix and U is upper triangular matrix + println("L:\n$l") + println("U:\n$u") + // and PA = LU + println("PA:\n${p dot a}") + println("LU:\n${l dot u}") + + /* Ax = b; + PAx = Pb; + LUx = Pb; + let y = Ux, then + Ly = Pb -- this system can be easily solved, since the matrix L is lower triangular; + Ux = y can be solved the same way, since the matrix L is upper triangular + */ + + + + // this function returns solution x of a system lx = b, l should be lower triangular + fun solveLT(l: DoubleTensor, b: DoubleTensor): DoubleTensor { + val n = l.shape[0] + val x = zeros(intArrayOf(n)) + for (i in 0 until n){ + x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)] + } + return x + } + + val y = solveLT(l, p dot b) + + // solveLT(l, b) function can be easily adapted for upper triangular matrix by the permutation matrix revMat + // create it by placing ones on side diagonal + val revMat = u.zeroesLike() + val n = revMat.shape[0] + for (i in 0 until n) { + revMat[intArrayOf(i, n - 1 - i)] = 1.0 + } + + // solution of system ux = b, u should be upper triangular + fun solveUT(u: DoubleTensor, b: DoubleTensor): DoubleTensor = revMat dot solveLT( + revMat dot u dot revMat, revMat dot b + ) + + val x = solveUT(u, y) + + println("True x:\n$trueX") + println("x founded with LU method:\n$x") + } +} \ No newline at end of file From 51f084d28be21118c403ce5ae29775ab894971ae Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 28 Apr 2021 17:07:10 +0100 Subject: [PATCH 247/393] merge PR --- .../main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index a9b154017..9318fe928 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -30,20 +30,17 @@ fun main() { println("Real alpha:\n$alpha") - // also take sample of size 20 from normal distribution for x TODO rename + // also take sample of size 20 from normal distribution for x val x = randNormal( intArrayOf(20, 5), randSeed ) // calculate y and add gaussian noise (N(0, 0.05)) - // TODO: please add an intercept: Y = beta * X + alpha + N(0,0.5) val y = x dot alpha y += y.randNormalLike(randSeed) * 0.05 // now restore the coefficient vector with OSL estimator with SVD - // TODO: you need to change accordingly [X 1] [alpha beta] = Y - // TODO: inverting [X 1] via SVD val (u, singValues, v) = x.svd() // we have to make sure the singular values of the matrix are not close to zero From 6f5b0f0a03e941b33d4adc22e341bce2f7d8bd00 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 29 Apr 2021 17:09:50 +0300 Subject: [PATCH 248/393] add README and documentation for the main functions of tensor algebra --- README.md | 12 + kmath-tensors/README.md | 37 +++ kmath-tensors/build.gradle.kts | 26 ++- kmath-tensors/docs/README-TEMPLATE.md | 7 + .../tensors/api/LinearOpsTensorAlgebra.kt | 84 ++++++- .../kmath/tensors/api/TensorAlgebra.kt | 211 +++++++++++++++++- .../algebras/BroadcastDoubleTensorAlgebra.kt | 4 + 7 files changed, 365 insertions(+), 16 deletions(-) create mode 100644 kmath-tensors/README.md create mode 100644 kmath-tensors/docs/README-TEMPLATE.md diff --git a/README.md b/README.md index 773eb6398..19c59e79e 100644 --- a/README.md +++ b/README.md @@ -230,6 +230,18 @@ One can still use generic algebras though. > **Maturity**: EXPERIMENTAL
+* ### [kmath-tensors](kmath-tensors) +> +> +> **Maturity**: PROTOTYPE +> +> **Features:** +> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) +> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. +> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. + +
+ * ### [kmath-viktor](kmath-viktor) > > diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md new file mode 100644 index 000000000..3b82829f0 --- /dev/null +++ b/kmath-tensors/README.md @@ -0,0 +1,37 @@ +# Module kmath-tensors + +Common linear algebra operations on tensors. + + - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) + - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. + - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. + + +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-7`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + maven { url 'https://dl.bintray.com/hotkeytlt/maven' } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap +} + +dependencies { + implementation 'space.kscience:kmath-tensors:0.3.0-dev-7' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + maven("https://dl.bintray.com/hotkeytlt/maven") // required for a +} + +dependencies { + implementation("space.kscience:kmath-tensors:0.3.0-dev-7") +} +``` diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts index 8e823416b..af5116022 100644 --- a/kmath-tensors/build.gradle.kts +++ b/kmath-tensors/build.gradle.kts @@ -11,6 +11,30 @@ kotlin.sourceSets { } } +tasks.dokkaHtml { + dependsOn(tasks.build) +} + readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + + feature( + id = "tensor algebra", + description = "Basic linear algebra operations on tensors (plus, dot, etc.)", + ref = "src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt" + ) + + feature( + id = "tensor algebra with broadcasting", + description = "Basic linear algebra operations implemented with broadcasting.", + ref = "src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt" + ) + + feature( + id = "linear algebra operations", + description = "Advanced linear algebra operations like LU decomposition, SVD, etc.", + ref = "src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt" + ) + } \ No newline at end of file diff --git a/kmath-tensors/docs/README-TEMPLATE.md b/kmath-tensors/docs/README-TEMPLATE.md new file mode 100644 index 000000000..5fd968afd --- /dev/null +++ b/kmath-tensors/docs/README-TEMPLATE.md @@ -0,0 +1,7 @@ +# Module kmath-tensors + +Common linear algebra operations on tensors. + +${features} + +${artifact} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 5cd48ca78..6735efacb 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -5,33 +5,99 @@ package space.kscience.kmath.tensors.api - +/** + * Common linear algebra operations. Operates on [TensorStructure]. + * + * @param T the type of items in the tensors. + */ public interface LinearOpsTensorAlgebra : TensorPartialDivisionAlgebra { - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.det + /** + * Computes the determinant of a square matrix input, or of each square matrix in a batched input. + * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.det + * + * @return the determinant. + */ public fun TensorStructure.det(): TensorStructure - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv + /** + * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input. + * Given a square matrix `a`, return the matrix `aInv` satisfying + * ``a.dot(aInv) = aInv.dot(a) = eye(a.shape[0])``. + * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv + * + * @return the multiplicative inverse of a matrix. + */ public fun TensorStructure.inv(): TensorStructure - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.cholesky + /** + * Cholesky decomposition. + * + * Computes the Cholesky decomposition of a Hermitian (or symmetric for real-valued matrices) + * positive-definite matrix or the Cholesky decompositions for a batch of such matrices. + * Each decomposition has the form: + * Given a tensor `input`, return the tensor `L` satisfying ``input = L * L.H``, + * where L is a lower-triangular matrix and L.H is the conjugate transpose of L, + * which is just a transpose for the case of real-valued input matrices. + * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.cholesky + * + * @return the batch of L matrices. + */ public fun TensorStructure.cholesky(): TensorStructure - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr + /** + * QR decomposition. + * + * Computes the QR decomposition of a matrix or a batch of matrices, and returns a namedtuple `(Q, R)` of tensors. + * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q * R``, + * with `Q` being an orthogonal matrix or batch of orthogonal matrices + * and `R` being an upper triangular matrix or batch of upper triangular matrices. + * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr + * + * @return tuple of Q and R tensors. + */ public fun TensorStructure.qr(): Pair, TensorStructure> - //https://pytorch.org/docs/stable/generated/torch.lu.html + /** + * TODO('Andrew') + * For more information: https://pytorch.org/docs/stable/generated/torch.lu.html + * + * @return ... + */ public fun TensorStructure.lu(): Pair, TensorStructure> - //https://pytorch.org/docs/stable/generated/torch.lu_unpack.html + /** + * TODO('Andrew') + * For more information: https://pytorch.org/docs/stable/generated/torch.lu_unpack.html + * + * @param luTensor ... + * @param pivotsTensor ... + * @return ... + */ public fun luPivot(luTensor: TensorStructure, pivotsTensor: TensorStructure): Triple, TensorStructure, TensorStructure> - //https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd + /** + * Singular Value Decomposition. + * + * Computes the singular value decomposition of either a matrix or batch of matrices `input`. + * The singular value decomposition is represented as a namedtuple `(U, S, V)`, + * such that ``input = U.dot(diagonalEmbedding(S).dot(V.T))``. + * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. + * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd + * + * @return the determinant. + */ public fun TensorStructure.svd(): Triple, TensorStructure, TensorStructure> - //https://pytorch.org/docs/stable/generated/torch.symeig.html + /** + * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, + * represented by a namedtuple (eigenvalues, eigenvectors). + * For more information: https://pytorch.org/docs/stable/generated/torch.symeig.html + * + * @return a namedtuple (eigenvalues, eigenvectors) + */ public fun TensorStructure.symEig(): Pair, TensorStructure> } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index c1657d916..92aafb8ea 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -5,44 +5,243 @@ package space.kscience.kmath.tensors.api -// https://proofwiki.org/wiki/Definition:Algebra_over_Ring +/** + * Basic linear algebra operations on [TensorStructure]. + * For more information: https://proofwiki.org/wiki/Definition:Algebra_over_Ring + * + * @param T the type of items in the tensors. + */ public interface TensorAlgebra { + /** + * Returns a single tensor value of unit dimension. The tensor shape must be equal to [1]. + * + * @return the value of a scalar tensor. + */ public fun TensorStructure.value(): T + /** + * Each element of the tensor [other] is added to this value. + * The resulting tensor is returned. + * + * @param other tensor to be added. + * @return the sum of this value and tensor [other]. + */ public operator fun T.plus(other: TensorStructure): TensorStructure + + /** + * Adds the scalar [value] to each element of this tensor and returns a new resulting tensor. + * + * @param value the number to be added to each element of this tensor. + * @return the sum of this tensor and [value]. + */ public operator fun TensorStructure.plus(value: T): TensorStructure + + /** + * Each element of the tensor [other] is added to each element of this tensor. + * The resulting tensor is returned. + * + * @param other tensor to be added. + * @return the sum of this tensor and [other]. + */ public operator fun TensorStructure.plus(other: TensorStructure): TensorStructure + + /** + * Adds the scalar [value] to each element of this tensor. + * + * @param value the number to be added to each element of this tensor. + */ public operator fun TensorStructure.plusAssign(value: T): Unit + + /** + * Each element of the tensor [other] is added to each element of this tensor. + * + * @param other tensor to be added. + */ public operator fun TensorStructure.plusAssign(other: TensorStructure): Unit + + /** + * Each element of the tensor [other] is subtracted from this value. + * The resulting tensor is returned. + * + * @param other tensor to be subtracted. + * @return the difference between this value and tensor [other]. + */ public operator fun T.minus(other: TensorStructure): TensorStructure + + /** + * Subtracts the scalar [value] from each element of this tensor and returns a new resulting tensor. + * + * @param value the number to be subtracted from each element of this tensor. + * @return the difference between this tensor and [value]. + */ public operator fun TensorStructure.minus(value: T): TensorStructure + + /** + * Each element of the tensor [other] is subtracted from each element of this tensor. + * The resulting tensor is returned. + * + * @param other tensor to be subtracted. + * @return the difference between this tensor and [other]. + */ public operator fun TensorStructure.minus(other: TensorStructure): TensorStructure + + /** + * Subtracts the scalar [value] from each element of this tensor. + * + * @param value the number to be subtracted from each element of this tensor. + */ public operator fun TensorStructure.minusAssign(value: T): Unit + + /** + * Each element of the tensor [other] is subtracted from each element of this tensor. + * + * @param other tensor to be subtracted. + */ public operator fun TensorStructure.minusAssign(other: TensorStructure): Unit + + /** + * Each element of the tensor [other] is multiplied by this value. + * The resulting tensor is returned. + * + * @param other tensor to be multiplied. + * @return the product of this value and tensor [other]. + */ public operator fun T.times(other: TensorStructure): TensorStructure + + /** + * Multiplies the scalar [value] by each element of this tensor and returns a new resulting tensor. + * + * @param value the number to be multiplied by each element of this tensor. + * @return the product of this tensor and [value]. + */ public operator fun TensorStructure.times(value: T): TensorStructure + + /** + * Each element of the tensor [other] is multiplied by each element of this tensor. + * The resulting tensor is returned. + * + * @param other tensor to be multiplied. + * @return the product of this tensor and [other]. + */ public operator fun TensorStructure.times(other: TensorStructure): TensorStructure + + /** + * Multiplies the scalar [value] by each element of this tensor. + * + * @param value the number to be multiplied by each element of this tensor. + */ public operator fun TensorStructure.timesAssign(value: T): Unit + + /** + * Each element of the tensor [other] is multiplied by each element of this tensor. + * + * @param other tensor to be multiplied. + */ public operator fun TensorStructure.timesAssign(other: TensorStructure): Unit + + /** + * Numerical negative, element-wise. + * + * @return tensor - negation of the original tensor. + */ public operator fun TensorStructure.unaryMinus(): TensorStructure - //https://pytorch.org/cppdocs/notes/tensor_indexing.html + /** + * Returns the tensor at index i + * For more information: https://pytorch.org/cppdocs/notes/tensor_indexing.html + * + * @param i index of the extractable tensor + * @return subtensor of the original tensor with index [i] + */ public operator fun TensorStructure.get(i: Int): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.transpose.html + /** + * Returns a tensor that is a transposed version of this tensor. The given dimensions [i] and [j] are swapped. + * For more information: https://pytorch.org/docs/stable/generated/torch.transpose.html + * + * @param i the first dimension to be transposed + * @param j the second dimension to be transposed + * @return transposed tensor + */ public fun TensorStructure.transpose(i: Int = -2, j: Int = -1): TensorStructure - //https://pytorch.org/docs/stable/tensor_view.html + /** + * Returns a new tensor with the same data as the self tensor but of a different shape. + * The returned tensor shares the same data and must have the same number of elements, but may have a different size + * For more information: https://pytorch.org/docs/stable/tensor_view.html + * + * @param shape the desired size + * @return tensor with new shape + */ public fun TensorStructure.view(shape: IntArray): TensorStructure + + /** + * View this tensor as the same size as [other]. + * ``this.viewAs(other) is equivalent to this.view(other.shape)``. + * For more information: https://pytorch.org/cppdocs/notes/tensor_indexing.html + * + * @param other the result tensor has the same size as other. + * @return the result tensor with the same size as other. + */ public fun TensorStructure.viewAs(other: TensorStructure): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.matmul.html + /** + * Matrix product of two tensors. + * + * The behavior depends on the dimensionality of the tensors as follows: + * 1. If both tensors are 1-dimensional, the dot product (scalar) is returned. + * + * 2. If both arguments are 2-dimensional, the matrix-matrix product is returned. + * + * 3. If the first argument is 1-dimensional and the second argument is 2-dimensional, + * a 1 is prepended to its dimension for the purpose of the matrix multiply. + * After the matrix multiply, the prepended dimension is removed. + * + * 4. If the first argument is 2-dimensional and the second argument is 1-dimensional, + * the matrix-vector product is returned. + * + * 5. If both arguments are at least 1-dimensional and at least one argument is N-dimensional (where N > 2), + * then a batched matrix multiply is returned. If the first argument is 1-dimensional, + * a 1 is prepended to its dimension for the purpose of the batched matrix multiply and removed after. + * If the second argument is 1-dimensional, a 1 is appended to its dimension for the purpose of the batched matrix + * multiple and removed after. + * The non-matrix (i.e. batch) dimensions are broadcasted (and thus must be broadcastable). + * For example, if `input` is a (j \times 1 \times n \times n) tensor and `other` is a + * (k \times n \times n) tensor, out will be a (j \times k \times n \times n) tensor. + * + * For more information: https://pytorch.org/docs/stable/generated/torch.matmul.html + * + * @param other tensor to be multiplied + * @return mathematical product of two tensors + */ public infix fun TensorStructure.dot(other: TensorStructure): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.diag_embed.html + /** + * Creates a tensor whose diagonals of certain 2D planes (specified by [dim1] and [dim2]) + * are filled by [diagonalEntries]. + * To facilitate creating batched diagonal matrices, + * the 2D planes formed by the last two dimensions of the returned tensor are chosen by default. + * + * The argument [offset] controls which diagonal to consider: + * 1. If [offset] = 0, it is the main diagonal. + * 2. If [offset] > 0, it is above the main diagonal. + * 3. If [offset] < 0, it is below the main diagonal. + * + * The size of the new matrix will be calculated + * to make the specified diagonal of the size of the last input dimension. + * For more information: https://pytorch.org/docs/stable/generated/torch.diag_embed.html + * + * @param diagonalEntries - the input tensor. Must be at least 1-dimensional. + * @param offset - which diagonal to consider. Default: 0 (main diagonal). + * @param dim1 - first dimension with respect to which to take diagonal. Default: -2. + * @param dim2 - second dimension with respect to which to take diagonal. Default: -1. + * + * @return tensor whose diagonals of certain 2D planes (specified by [dim1] and [dim2]) + * are filled by [diagonalEntries] + */ public fun diagonalEmbedding( diagonalEntries: TensorStructure, offset: Int = 0, diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt index 1b00197ff..a49d9ab29 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -10,6 +10,10 @@ import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.broadcastTensors import space.kscience.kmath.tensors.core.broadcastTo +/** + * Basic linear algebra operations implemented with broadcasting. + * For more information: https://pytorch.org/docs/stable/notes/broadcasting.html + */ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { From 64c6cbf8603a267f7a85af65f16d567c448eeb0a Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 29 Apr 2021 17:21:29 +0300 Subject: [PATCH 249/393] change tuple to pair/triple --- .../kmath/tensors/api/LinearOpsTensorAlgebra.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 6735efacb..aa10ae49b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -49,13 +49,13 @@ public interface LinearOpsTensorAlgebra : /** * QR decomposition. * - * Computes the QR decomposition of a matrix or a batch of matrices, and returns a namedtuple `(Q, R)` of tensors. + * Computes the QR decomposition of a matrix or a batch of matrices, and returns a pair `(Q, R)` of tensors. * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q * R``, * with `Q` being an orthogonal matrix or batch of orthogonal matrices * and `R` being an upper triangular matrix or batch of upper triangular matrices. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr * - * @return tuple of Q and R tensors. + * @return pair of Q and R tensors. */ public fun TensorStructure.qr(): Pair, TensorStructure> @@ -82,7 +82,7 @@ public interface LinearOpsTensorAlgebra : * Singular Value Decomposition. * * Computes the singular value decomposition of either a matrix or batch of matrices `input`. - * The singular value decomposition is represented as a namedtuple `(U, S, V)`, + * The singular value decomposition is represented as a triple `(U, S, V)`, * such that ``input = U.dot(diagonalEmbedding(S).dot(V.T))``. * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd @@ -93,10 +93,10 @@ public interface LinearOpsTensorAlgebra : /** * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, - * represented by a namedtuple (eigenvalues, eigenvectors). + * represented by a pair (eigenvalues, eigenvectors). * For more information: https://pytorch.org/docs/stable/generated/torch.symeig.html * - * @return a namedtuple (eigenvalues, eigenvectors) + * @return a pair (eigenvalues, eigenvectors) */ public fun TensorStructure.symEig(): Pair, TensorStructure> From b9f1f0e5259b771727a4cdbdfbefc5d5047cf08e Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 29 Apr 2021 20:00:05 +0300 Subject: [PATCH 250/393] fixes --- .../kmath/tensors/api/TensorAlgebra.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 92aafb8ea..62d4a1b89 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -145,7 +145,7 @@ public interface TensorAlgebra { /** * Numerical negative, element-wise. * - * @return tensor - negation of the original tensor. + * @return tensor negation of the original tensor. */ public operator fun TensorStructure.unaryMinus(): TensorStructure @@ -209,8 +209,8 @@ public interface TensorAlgebra { * If the second argument is 1-dimensional, a 1 is appended to its dimension for the purpose of the batched matrix * multiple and removed after. * The non-matrix (i.e. batch) dimensions are broadcasted (and thus must be broadcastable). - * For example, if `input` is a (j \times 1 \times n \times n) tensor and `other` is a - * (k \times n \times n) tensor, out will be a (j \times k \times n \times n) tensor. + * For example, if `input` is a (j × 1 × n × n) tensor and `other` is a + * (k × n × n) tensor, out will be a (j × k × n × n) tensor. * * For more information: https://pytorch.org/docs/stable/generated/torch.matmul.html * @@ -227,17 +227,17 @@ public interface TensorAlgebra { * * The argument [offset] controls which diagonal to consider: * 1. If [offset] = 0, it is the main diagonal. - * 2. If [offset] > 0, it is above the main diagonal. - * 3. If [offset] < 0, it is below the main diagonal. + * 1. If [offset] > 0, it is above the main diagonal. + * 1. If [offset] < 0, it is below the main diagonal. * * The size of the new matrix will be calculated * to make the specified diagonal of the size of the last input dimension. * For more information: https://pytorch.org/docs/stable/generated/torch.diag_embed.html * - * @param diagonalEntries - the input tensor. Must be at least 1-dimensional. - * @param offset - which diagonal to consider. Default: 0 (main diagonal). - * @param dim1 - first dimension with respect to which to take diagonal. Default: -2. - * @param dim2 - second dimension with respect to which to take diagonal. Default: -1. + * @param diagonalEntries the input tensor. Must be at least 1-dimensional. + * @param offset which diagonal to consider. Default: 0 (main diagonal). + * @param dim1 first dimension with respect to which to take diagonal. Default: -2. + * @param dim2 second dimension with respect to which to take diagonal. Default: -1. * * @return tensor whose diagonals of certain 2D planes (specified by [dim1] and [dim2]) * are filled by [diagonalEntries] From 432f404d7c00c4d090f5496ae8ffb5e69d9330d8 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 29 Apr 2021 18:45:46 +0100 Subject: [PATCH 251/393] More descriptions --- kmath-tensors/README.md | 13 +++--- .../tensors/api/AnalyticTensorAlgebra.kt | 38 +++++++++-------- .../tensors/api/LinearOpsTensorAlgebra.kt | 2 +- .../kmath/tensors/api/TensorAlgebra.kt | 2 +- .../api/TensorPartialDivisionAlgebra.kt | 42 ++++++++++++++++++- 5 files changed, 72 insertions(+), 25 deletions(-) diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 3b82829f0..24d46cd16 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -1,12 +1,15 @@ # Module kmath-tensors -Common linear algebra operations on tensors. - - - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) - - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. - - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. +Common operations on tensors, the API consists of: + - [TensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic algebra operations on tensors (plus, dot, etc.) + - [TensorPartialDivisionAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt) : Emulates an algebra over a field + - [LinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Linear algebra operations including LU, QR, Cholesky LL and SVD decompositions + - [AnalyticTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt) : Element-wise analytic operations +The library offers a multiplatform implementation for this interface over the `Double`'s. As the highlight, the user can find: + - [BroadcastDoubleTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic algebra operations implemented with broadcasting. + - [DoubleLinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt) : Includes the power method for SVD and the spectrum of symmetric matrices. ## Artifact: The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-7`. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 315f39027..5c92c56c4 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -5,59 +5,63 @@ package space.kscience.kmath.tensors.api - +/** + * Element-wise analytic operations on [TensorStructure]. + * + * @param T the type of items closed under analytic functions in the tensors. + */ public interface AnalyticTensorAlgebra : TensorPartialDivisionAlgebra { - //https://pytorch.org/docs/stable/generated/torch.exp.html + //For information: https://pytorch.org/docs/stable/generated/torch.exp.html public fun TensorStructure.exp(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.log.html + //For information: https://pytorch.org/docs/stable/generated/torch.log.html public fun TensorStructure.log(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.sqrt.html + //For information: https://pytorch.org/docs/stable/generated/torch.sqrt.html public fun TensorStructure.sqrt(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos + //For information: https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos public fun TensorStructure.cos(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.acos.html#torch.acos + //For information: https://pytorch.org/docs/stable/generated/torch.acos.html#torch.acos public fun TensorStructure.acos(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.cosh + //For information: https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.cosh public fun TensorStructure.cosh(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.acosh + //For information: https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.acosh public fun TensorStructure.acosh(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sin + //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sin public fun TensorStructure.sin(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asin + //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asin public fun TensorStructure.asin(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sinh + //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sinh public fun TensorStructure.sinh(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asinh + //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asinh public fun TensorStructure.asinh(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.tan + //For information: https://pytorch.org/docs/stable/generated/torch.atan.html#torch.tan public fun TensorStructure.tan(): TensorStructure //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.atan public fun TensorStructure.atan(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.tanh + //For information: https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.tanh public fun TensorStructure.tanh(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.atanh + //For information: https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.atanh public fun TensorStructure.atanh(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.ceil.html#torch.ceil + //For information: https://pytorch.org/docs/stable/generated/torch.ceil.html#torch.ceil public fun TensorStructure.ceil(): TensorStructure - //https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor + //For information: https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor public fun TensorStructure.floor(): TensorStructure } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index aa10ae49b..7a19c5d5a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.tensors.api /** * Common linear algebra operations. Operates on [TensorStructure]. * - * @param T the type of items in the tensors. + * @param T the type of items closed under division in the tensors. */ public interface LinearOpsTensorAlgebra : TensorPartialDivisionAlgebra { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 62d4a1b89..338064231 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.api /** - * Basic linear algebra operations on [TensorStructure]. + * Algebra over a ring on [TensorStructure]. * For more information: https://proofwiki.org/wiki/Definition:Algebra_over_Ring * * @param T the type of items in the tensors. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt index 4dab3dd07..eccc6fa0d 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt @@ -5,12 +5,52 @@ package space.kscience.kmath.tensors.api -// https://proofwiki.org/wiki/Definition:Division_Algebra +/** + * Algebra over a field with partial division on [TensorStructure]. + * For more information: https://proofwiki.org/wiki/Definition:Division_Algebra + * + * @param T the type of items closed under division in the tensors. + */ public interface TensorPartialDivisionAlgebra : TensorAlgebra { + + /** + * Each element of the tensor [other] is divided by this value. + * The resulting tensor is returned. + * + * @param other tensor to divide by. + * @return the division of this value by the tensor [other]. + */ public operator fun T.div(other: TensorStructure): TensorStructure + + /** + * Divide by the scalar [value] each element of this tensor returns a new resulting tensor. + * + * @param value the number to divide by each element of this tensor. + * @return the division of this tensor by the [value]. + */ public operator fun TensorStructure.div(value: T): TensorStructure + + /** + * Each element of the tensor [other] is divided by each element of this tensor. + * The resulting tensor is returned. + * + * @param other tensor to be divided by. + * @return the division of this tensor by [other]. + */ public operator fun TensorStructure.div(other: TensorStructure): TensorStructure + + /** + * Divides by the scalar [value] each element of this tensor. + * + * @param value the number to divide by each element of this tensor. + */ public operator fun TensorStructure.divAssign(value: T) + + /** + * Each element of this tensor is divided by each element of the [other] tensor. + * + * @param other tensor to be divide by. + */ public operator fun TensorStructure.divAssign(other: TensorStructure) } From cba62a9468c84bb476dbf905bd44c4df90d9b735 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 29 Apr 2021 18:48:41 +0100 Subject: [PATCH 252/393] English typo --- kmath-tensors/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 24d46cd16..a81b7277c 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -7,9 +7,9 @@ Common operations on tensors, the API consists of: - [LinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Linear algebra operations including LU, QR, Cholesky LL and SVD decompositions - [AnalyticTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt) : Element-wise analytic operations -The library offers a multiplatform implementation for this interface over the `Double`'s. As the highlight, the user can find: +The library offers a multiplatform implementation for this interface over the `Double`'s. As a highlight, the user can find: - [BroadcastDoubleTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic algebra operations implemented with broadcasting. - - [DoubleLinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt) : Includes the power method for SVD and the spectrum of symmetric matrices. + - [DoubleLinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt) : Contains the power method for SVD and the spectrum of symmetric matrices. ## Artifact: The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-7`. From 09f0a2879e50c364ee969930576af8e453e32748 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 30 Apr 2021 11:08:22 +0300 Subject: [PATCH 253/393] refactor lu + docs --- .../tensors/LinearSystemSolvingWithLUP.kt | 3 +-- .../tensors/api/LinearOpsTensorAlgebra.kt | 22 +++++++------------ .../algebras/DoubleLinearOpsTensorAlgebra.kt | 17 ++++++++++---- .../core/TestDoubleLinearOpsAlgebra.kt | 4 +--- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index 526b6781f..38d8c1437 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -42,8 +42,7 @@ fun main () { // solve `Ax = b` system using LUP decomposition // get P, L, U such that PA = LU - val (lu, pivots) = a.lu() - val (p, l, u) = luPivot(lu, pivots) + val (p, l, u) = a.lu() // check that P is permutation matrix println("P:\n$p") diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 7a19c5d5a..bcbb52a1b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -60,23 +60,17 @@ public interface LinearOpsTensorAlgebra : public fun TensorStructure.qr(): Pair, TensorStructure> /** - * TODO('Andrew') - * For more information: https://pytorch.org/docs/stable/generated/torch.lu.html + * LUP decomposition * - * @return ... - */ - public fun TensorStructure.lu(): Pair, TensorStructure> - - /** - * TODO('Andrew') - * For more information: https://pytorch.org/docs/stable/generated/torch.lu_unpack.html + * Computes the LUP decomposition of a matrix or a batch of matrices. + * Given a tensor `input`, return tensors (P, L, U) satisfying ``P * input = L * U``, + * with `P` being a permutation matrix or batch of matrices, + * `L` being a lower triangular matrix or batch of matrices, + * `U` being an upper triangular matrix or batch of matrices. * - * @param luTensor ... - * @param pivotsTensor ... - * @return ... + * * @return triple of P, L and U tensors */ - public fun luPivot(luTensor: TensorStructure, pivotsTensor: TensorStructure): - Triple, TensorStructure, TensorStructure> + public fun TensorStructure.lu(): Triple, TensorStructure, TensorStructure> /** * Singular Value Decomposition. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 62629f3db..97eed289a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -29,13 +29,13 @@ public class DoubleLinearOpsTensorAlgebra : override fun TensorStructure.det(): DoubleTensor = detLU(1e-9) - public fun TensorStructure.lu(epsilon: Double): Pair = + public fun TensorStructure.luFactor(epsilon: Double): Pair = computeLU(tensor, epsilon) ?: throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon") - override fun TensorStructure.lu(): Pair = lu(1e-9) + public fun TensorStructure.luFactor(): Pair = luFactor(1e-9) - override fun luPivot( + public fun luPivot( luTensor: TensorStructure, pivotsTensor: TensorStructure ): Triple { @@ -156,7 +156,7 @@ public class DoubleLinearOpsTensorAlgebra : } public fun TensorStructure.invLU(epsilon: Double = 1e-9): DoubleTensor { - val (luTensor, pivotsTensor) = lu(epsilon) + val (luTensor, pivotsTensor) = luFactor(epsilon) val invTensor = luTensor.zeroesLike() val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) @@ -167,6 +167,15 @@ public class DoubleLinearOpsTensorAlgebra : return invTensor } + + public fun TensorStructure.lu(epsilon: Double = 1e-9): Triple { + val (lu, pivots) = this.luFactor(epsilon) + return luPivot(lu, pivots) + } + + override fun TensorStructure.lu(): Triple = lu(1e-9) + + } public inline fun DoubleLinearOpsTensorAlgebra(block: DoubleLinearOpsTensorAlgebra.() -> R): R = diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 6120f0e4a..1f7e955d4 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -124,9 +124,7 @@ class TestDoubleLinearOpsTensorAlgebra { ) val tensor = fromArray(shape, buffer) - val (lu, pivots) = tensor.lu() - - val (p, l, u) = luPivot(lu, pivots) + val (p, l, u) = tensor.lu() assertTrue { p.shape contentEquals shape } assertTrue { l.shape contentEquals shape } From b546f3f78bf019c65b6bf4e1dda7cf521da46884 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 09:19:30 +0100 Subject: [PATCH 254/393] Merge PR --- .../kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 97eed289a..03f383728 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -116,7 +116,7 @@ public class DoubleLinearOpsTensorAlgebra : override fun TensorStructure.symEig(): Pair = symEig(epsilon = 1e-15) - //http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html + //For information: http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html public fun TensorStructure.symEig(epsilon: Double): Pair { checkSymmetric(tensor, epsilon) val (u, s, v) = tensor.svd(epsilon) From bd068b2c1438e912a1a0b96bab72ffe55478374e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 09:54:25 +0100 Subject: [PATCH 255/393] Smaller SVD test --- .../kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 1f7e955d4..b2ef6b4c4 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -163,7 +163,7 @@ class TestDoubleLinearOpsTensorAlgebra { @Test fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { - val tensor = randNormal(intArrayOf(1, 15, 4, 7, 5, 3), 0) + val tensor = randNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) assertTrue(tensor.eq(tensorSVD)) @@ -171,7 +171,7 @@ class TestDoubleLinearOpsTensorAlgebra { @Test fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { - val tensor = randNormal(shape = intArrayOf(5, 3, 3), 0) + val tensor = randNormal(shape = intArrayOf(2, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) From 598b2e158724e4d9dd73d8d80a361684893071cd Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 28 Apr 2021 18:03:28 +0700 Subject: [PATCH 256/393] Rewrite EJML module by dropping ejml-simple abstraction level; multiple build script changes --- .github/workflows/pages.yml | 4 +- CHANGELOG.md | 3 +- benchmarks/build.gradle.kts | 6 +- .../kscience/kmath/benchmarks/DotBenchmark.kt | 10 +- .../benchmarks/MatrixInverseBenchmark.kt | 21 +- build.gradle.kts | 30 +-- docs/templates/ARTIFACT-TEMPLATE.md | 6 +- examples/build.gradle.kts | 7 +- kmath-ast/README.md | 6 +- kmath-complex/README.md | 6 +- kmath-core/README.md | 6 +- kmath-ejml/README.md | 12 +- kmath-ejml/build.gradle.kts | 8 +- .../kscience/kmath/ejml/EjmlLinearSpace.kt | 251 +++++++++++------- .../space/kscience/kmath/ejml/EjmlMatrix.kt | 24 +- .../space/kscience/kmath/ejml/EjmlVector.kt | 36 +-- .../kscience/kmath/ejml/EjmlMatrixTest.kt | 53 ++-- .../kscience/kmath/ejml/EjmlVectorTest.kt | 23 +- kmath-for-real/README.md | 2 - kmath-functions/README.md | 2 - kmath-kotlingrad/build.gradle.kts | 4 +- kmath-nd4j/README.md | 6 +- kmath-viktor/build.gradle.kts | 4 +- 23 files changed, 281 insertions(+), 249 deletions(-) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 82b0fb303..c70227fce 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -30,9 +30,7 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - name: Build - run: | - ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace - mv build/dokka/htmlMultiModule/-modules.html build/dokka/htmlMultiModule/index.html + run: ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace - name: Deploy to GitHub Pages uses: JamesIves/github-pages-deploy-action@4.1.0 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 7464695ec..4266c5b70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ - Blocking chains and Statistics - Multiplatform integration - Integration for any Field element -- Extendend operations for ND4J fields +- Extended operations for ND4J fields ### Changed - Exponential operations merged with hyperbolic functions @@ -24,6 +24,7 @@ - Redesign MST. Remove MSTExpression. - Move MST to core - Separated benchmarks and examples +- Rewritten EJML module without ejml-simple ### Deprecated diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 88f034a2a..98ffc5a96 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -9,14 +9,10 @@ sourceSets.register("benchmarks") repositories { mavenCentral() - jcenter() maven("https://repo.kotlin.link") maven("https://clojars.org/repo") - maven("https://dl.bintray.com/egor-bogomolov/astminer/") - maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://jitpack.io") - maven { - setUrl("http://logicrunch.research.it.uu.se/maven/") + maven("http://logicrunch.research.it.uu.se/maven") { isAllowInsecureProtocol = true } } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt index 23e73cb5f..2c5a03a97 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt @@ -10,7 +10,7 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import space.kscience.kmath.commons.linear.CMLinearSpace -import space.kscience.kmath.ejml.EjmlLinearSpace +import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.invoke import space.kscience.kmath.operations.DoubleField @@ -29,8 +29,8 @@ internal class DotBenchmark { val cmMatrix1 = CMLinearSpace { matrix1.toCM() } val cmMatrix2 = CMLinearSpace { matrix2.toCM() } - val ejmlMatrix1 = EjmlLinearSpace { matrix1.toEjml() } - val ejmlMatrix2 = EjmlLinearSpace { matrix2.toEjml() } + val ejmlMatrix1 = EjmlLinearSpaceDDRM { matrix1.toEjml() } + val ejmlMatrix2 = EjmlLinearSpaceDDRM { matrix2.toEjml() } } @Benchmark @@ -42,14 +42,14 @@ internal class DotBenchmark { @Benchmark fun ejmlDot(blackhole: Blackhole) { - EjmlLinearSpace { + EjmlLinearSpaceDDRM { blackhole.consume(ejmlMatrix1 dot ejmlMatrix2) } } @Benchmark fun ejmlDotWithConversion(blackhole: Blackhole) { - EjmlLinearSpace { + EjmlLinearSpaceDDRM { blackhole.consume(matrix1 dot matrix2) } } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt index d1803e389..7bb32af28 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt @@ -11,25 +11,26 @@ import kotlinx.benchmark.Scope import kotlinx.benchmark.State import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.commons.linear.inverse -import space.kscience.kmath.ejml.EjmlLinearSpace -import space.kscience.kmath.ejml.inverse +import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM +import space.kscience.kmath.linear.InverseMatrixFeature import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.inverseWithLup import space.kscience.kmath.linear.invoke +import space.kscience.kmath.nd.getFeature import kotlin.random.Random @State(Scope.Benchmark) internal class MatrixInverseBenchmark { - companion object { - val random = Random(1224) - const val dim = 100 + private companion object { + private val random = Random(1224) + private const val dim = 100 private val space = LinearSpace.real //creating invertible matrix - val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } - val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 } - val matrix = space { l dot u } + private val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } + private val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 } + private val matrix = space { l dot u } } @Benchmark @@ -46,8 +47,8 @@ internal class MatrixInverseBenchmark { @Benchmark fun ejmlInverse(blackhole: Blackhole) { - with(EjmlLinearSpace) { - blackhole.consume(inverse(matrix)) + with(EjmlLinearSpaceDDRM) { + blackhole.consume(matrix.getFeature>()?.inverse) } } } diff --git a/build.gradle.kts b/build.gradle.kts index 4e0b6f256..506f51a0e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,14 +4,12 @@ plugins { allprojects { repositories { - jcenter() maven("https://clojars.org/repo") - maven("https://dl.bintray.com/egor-bogomolov/astminer/") - maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://jitpack.io") - maven("http://logicrunch.research.it.uu.se/maven/") { + maven("http://logicrunch.research.it.uu.se/maven") { isAllowInsecureProtocol = true } + maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven") mavenCentral() } @@ -23,22 +21,16 @@ subprojects { if (name.startsWith("kmath")) apply() afterEvaluate { - tasks.withType { - dokkaSourceSets.all { - val readmeFile = File(this@subprojects.projectDir, "./README.md") - if (readmeFile.exists()) - includes.setFrom(includes + readmeFile.absolutePath) + tasks.withType { + dependsOn(tasks.getByName("assemble")) - arrayOf( - "http://ejml.org/javadoc/", - "https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/", - "https://deeplearning4j.org/api/latest/" - ).map { java.net.URL("${it}package-list") to java.net.URL(it) }.forEach { (a, b) -> - externalDocumentationLink { - packageListUrl.set(a) - url.set(b) - } - } + dokkaSourceSets.all { + val readmeFile = File(this@subprojects.projectDir, "README.md") + if (readmeFile.exists()) includes.setFrom(includes + readmeFile.absolutePath) + externalDocumentationLink("http://ejml.org/javadoc/") + externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/") + externalDocumentationLink("https://deeplearning4j.org/api/latest/") + externalDocumentationLink("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/") } } } diff --git a/docs/templates/ARTIFACT-TEMPLATE.md b/docs/templates/ARTIFACT-TEMPLATE.md index 01d9c51da..1bac2a8ff 100644 --- a/docs/templates/ARTIFACT-TEMPLATE.md +++ b/docs/templates/ARTIFACT-TEMPLATE.md @@ -6,8 +6,7 @@ The Maven coordinates of this project are `${group}:${name}:${version}`. ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -18,8 +17,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 56feee9dc..571949b7b 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -4,14 +4,11 @@ plugins { repositories { mavenCentral() - jcenter() maven("https://repo.kotlin.link") maven("https://clojars.org/repo") - maven("https://dl.bintray.com/egor-bogomolov/astminer/") - maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://jitpack.io") - maven{ - setUrl("http://logicrunch.research.it.uu.se/maven/") + maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers") + maven("http://logicrunch.research.it.uu.se/maven") { isAllowInsecureProtocol = true } } diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 1ee78956e..4de165e72 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -16,8 +16,7 @@ The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-7` ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -28,8 +27,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 70beab95a..06e10fa7a 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -14,8 +14,7 @@ The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-de ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -26,8 +25,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { diff --git a/kmath-core/README.md b/kmath-core/README.md index e28873045..36b30efcc 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -21,8 +21,7 @@ The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-7 ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -33,8 +32,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index 3bf29f803..97c5ae115 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -2,9 +2,9 @@ EJML based linear algebra implementation. - - [ejml-vector](src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix. - - [ejml-matrix](src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix. - - [ejml-linear-space](src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix. + - [ejml-vector](src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : Point implementations. + - [ejml-matrix](src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : Matrix implementation. + - [ejml-linear-space](src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : LinearSpace implementations. ## Artifact: @@ -15,8 +15,7 @@ The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-7 ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -27,8 +26,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index d3a49aeb0..c8e2ecd8b 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } dependencies { - api("org.ejml:ejml-simple:0.40") + api("org.ejml:ejml-ddense:0.40") api(project(":kmath-core")) } @@ -14,19 +14,19 @@ readme { feature( id = "ejml-vector", - description = "The Point implementation using SimpleMatrix.", + description = "Point implementations.", ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt" ) feature( id = "ejml-matrix", - description = "The Matrix implementation using SimpleMatrix.", + description = "Matrix implementation.", ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt" ) feature( id = "ejml-linear-space", - description = "The LinearSpace implementation using SimpleMatrix.", + description = "LinearSpace implementations.", ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt" ) } diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index 4b6421c9b..71cae4829 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -5,45 +5,71 @@ package space.kscience.kmath.ejml +import org.ejml.data.DMatrix +import org.ejml.data.DMatrixD1 +import org.ejml.data.DMatrixRMaj +import org.ejml.dense.row.CommonOps_DDRM import org.ejml.dense.row.factory.DecompositionFactory_DDRM -import org.ejml.simple.SimpleMatrix import space.kscience.kmath.linear.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureFeature -import space.kscience.kmath.nd.getFeature import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.Ring import space.kscience.kmath.structures.DoubleBuffer import kotlin.reflect.KClass import kotlin.reflect.cast /** - * Represents context of basic operations operating with [EjmlMatrix]. + * [LinearSpace] implementation specialized for a certain EJML type. + * + * @param T the type of items in the matrices. + * @param A the element context type. + * @param M the EJML matrix type. + * @author Iaroslav Postovalov + */ +public abstract class EjmlLinearSpace, M : org.ejml.data.Matrix> : LinearSpace { + /** + * Converts this matrix to EJML one. + */ + public abstract fun Matrix.toEjml(): EjmlMatrix + + /** + * Converts this vector to EJML one. + */ + public abstract fun Point.toEjml(): EjmlVector + + public abstract override fun buildMatrix( + rows: Int, + columns: Int, + initializer: A.(i: Int, j: Int) -> T, + ): EjmlMatrix + + public abstract override fun buildVector(size: Int, initializer: A.(Int) -> T): EjmlVector +} + +/** + * [EjmlLinearSpace] implementation based on [CommonOps_DDRM], [DecompositionFactory_DDRM] operations and + * [DMatrixRMaj] matrices. * * @author Iaroslav Postovalov - * @author Alexander Nozik */ -public object EjmlLinearSpace : LinearSpace { +public object EjmlLinearSpaceDDRM : EjmlLinearSpace() { /** * The [DoubleField] reference. */ public override val elementAlgebra: DoubleField get() = DoubleField - /** - * Converts this matrix to EJML one. - */ - @OptIn(UnstableKMathAPI::class) - public fun Matrix.toEjml(): EjmlMatrix = when (val matrix = origin) { - is EjmlMatrix -> matrix + @Suppress("UNCHECKED_CAST") + public override fun Matrix.toEjml(): EjmlDoubleMatrix = when { + this is EjmlDoubleMatrix<*> && origin is DMatrixRMaj -> this as EjmlDoubleMatrix else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } } - /** - * Converts this vector to EJML one. - */ - public fun Point.toEjml(): EjmlVector = when (this) { - is EjmlVector -> this - else -> EjmlVector(SimpleMatrix(size, 1).also { - (0 until it.numRows()).forEach { row -> it[row, 0] = get(row) } + @Suppress("UNCHECKED_CAST") + public override fun Point.toEjml(): EjmlDoubleVector = when { + this is EjmlDoubleVector<*> && origin is DMatrixRMaj -> this as EjmlDoubleVector + else -> EjmlDoubleVector(DMatrixRMaj(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } }) } @@ -51,159 +77,178 @@ public object EjmlLinearSpace : LinearSpace { rows: Int, columns: Int, initializer: DoubleField.(i: Int, j: Int) -> Double, - ): EjmlMatrix = EjmlMatrix(SimpleMatrix(rows, columns).also { + ): EjmlDoubleMatrix = EjmlDoubleMatrix(DMatrixRMaj(rows, columns).also { (0 until rows).forEach { row -> - (0 until columns).forEach { col -> it[row, col] = DoubleField.initializer(row, col) } + (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } } }) - public override fun buildVector(size: Int, initializer: DoubleField.(Int) -> Double): Point = - EjmlVector(SimpleMatrix(size, 1).also { - (0 until it.numRows()).forEach { row -> it[row, 0] = DoubleField.initializer(row) } - }) + public override fun buildVector( + size: Int, + initializer: DoubleField.(Int) -> Double, + ): EjmlDoubleVector = EjmlDoubleVector(DMatrixRMaj(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } + }) - private fun SimpleMatrix.wrapMatrix() = EjmlMatrix(this) - private fun SimpleMatrix.wrapVector() = EjmlVector(this) + private fun T.wrapMatrix() = EjmlDoubleMatrix(this) + private fun T.wrapVector() = EjmlDoubleVector(this) public override fun Matrix.unaryMinus(): Matrix = this * (-1.0) - public override fun Matrix.dot(other: Matrix): EjmlMatrix = - EjmlMatrix(toEjml().origin.mult(other.toEjml().origin)) + public override fun Matrix.dot(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.mult(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } - public override fun Matrix.dot(vector: Point): EjmlVector = - EjmlVector(toEjml().origin.mult(vector.toEjml().origin)) + public override fun Matrix.dot(vector: Point): EjmlDoubleVector { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.mult(toEjml().origin, vector.toEjml().origin, out) + return out.wrapVector() + } - public override operator fun Matrix.minus(other: Matrix): EjmlMatrix = - (toEjml().origin - other.toEjml().origin).wrapMatrix() + public override operator fun Matrix.minus(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.subtract(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } - public override operator fun Matrix.times(value: Double): EjmlMatrix = - toEjml().origin.scale(value).wrapMatrix() + public override operator fun Matrix.times(value: Double): EjmlDoubleMatrix { + val res = this.toEjml().origin.copy() + CommonOps_DDRM.scale(value, res) + return res.wrapMatrix() + } - public override fun Point.unaryMinus(): EjmlVector = - toEjml().origin.negative().wrapVector() + public override fun Point.unaryMinus(): EjmlDoubleVector { + val out = toEjml().origin.copy() + CommonOps_DDRM.changeSign(out) + return out.wrapVector() + } - public override fun Matrix.plus(other: Matrix): EjmlMatrix = - (toEjml().origin + other.toEjml().origin).wrapMatrix() + public override fun Matrix.plus(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.add(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } - public override fun Point.plus(other: Point): EjmlVector = - (toEjml().origin + other.toEjml().origin).wrapVector() + public override fun Point.plus(other: Point): EjmlDoubleVector { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.add(toEjml().origin, other.toEjml().origin, out) + return out.wrapVector() + } - public override fun Point.minus(other: Point): EjmlVector = - (toEjml().origin - other.toEjml().origin).wrapVector() + public override fun Point.minus(other: Point): EjmlDoubleVector { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.subtract(toEjml().origin, other.toEjml().origin, out) + return out.wrapVector() + } - public override fun Double.times(m: Matrix): EjmlMatrix = - m.toEjml().origin.scale(this).wrapMatrix() + public override fun Double.times(m: Matrix): EjmlDoubleMatrix = m * this - public override fun Point.times(value: Double): EjmlVector = - toEjml().origin.scale(value).wrapVector() + public override fun Point.times(value: Double): EjmlDoubleVector { + val res = this.toEjml().origin.copy() + CommonOps_DDRM.scale(value, res) + return res.wrapVector() + } - public override fun Double.times(v: Point): EjmlVector = - v.toEjml().origin.scale(this).wrapVector() + public override fun Double.times(v: Point): EjmlDoubleVector = v * this @UnstableKMathAPI public override fun getFeature(structure: Matrix, type: KClass): F? { - //Return the feature if it is intrinsic to the structure + // Return the feature if it is intrinsic to the structure structure.getFeature(type)?.let { return it } val origin = structure.toEjml().origin return when (type) { InverseMatrixFeature::class -> object : InverseMatrixFeature { - override val inverse: Matrix by lazy { EjmlMatrix(origin.invert()) } + override val inverse: Matrix by lazy { + val res = origin.copy() + CommonOps_DDRM.invert(res) + EjmlDoubleMatrix(res) + } } DeterminantFeature::class -> object : DeterminantFeature { - override val determinant: Double by lazy(origin::determinant) + override val determinant: Double by lazy { CommonOps_DDRM.det(DMatrixRMaj(origin)) } } SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { private val svd by lazy { - DecompositionFactory_DDRM.svd(origin.numRows(), origin.numCols(), true, true, false) - .apply { decompose(origin.ddrm.copy()) } + DecompositionFactory_DDRM.svd(origin.numRows, origin.numCols, true, true, false) + .apply { decompose(origin.copy()) } } - override val u: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getU(null, false))) } - override val s: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getW(null))) } - override val v: Matrix by lazy { EjmlMatrix(SimpleMatrix(svd.getV(null, false))) } + override val u: Matrix by lazy { EjmlDoubleMatrix(svd.getU(null, false)) } + override val s: Matrix by lazy { EjmlDoubleMatrix(svd.getW(null)) } + override val v: Matrix by lazy { EjmlDoubleMatrix(svd.getV(null, false)) } override val singularValues: Point by lazy { DoubleBuffer(svd.singularValues) } } QRDecompositionFeature::class -> object : QRDecompositionFeature { private val qr by lazy { - DecompositionFactory_DDRM.qr().apply { decompose(origin.ddrm.copy()) } + DecompositionFactory_DDRM.qr().apply { decompose(origin.copy()) } } override val q: Matrix by lazy { - EjmlMatrix(SimpleMatrix(qr.getQ(null, false))) + OrthogonalFeature + EjmlDoubleMatrix(qr.getQ(null, false)) + OrthogonalFeature } - override val r: Matrix by lazy { EjmlMatrix(SimpleMatrix(qr.getR(null, false))) + UFeature } + override val r: Matrix by lazy { EjmlDoubleMatrix(qr.getR(null, false)) + UFeature } } CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { override val l: Matrix by lazy { val cholesky = - DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.ddrm.copy()) } + DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) } - EjmlMatrix(SimpleMatrix(cholesky.getT(null))) + LFeature + EjmlDoubleMatrix(cholesky.getT(null)) + LFeature } } LupDecompositionFeature::class -> object : LupDecompositionFeature { private val lup by lazy { - DecompositionFactory_DDRM.lu(origin.numRows(), origin.numCols()) - .apply { decompose(origin.ddrm.copy()) } + DecompositionFactory_DDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) } } override val l: Matrix by lazy { - EjmlMatrix(SimpleMatrix(lup.getLower(null))) + LFeature + EjmlDoubleMatrix(lup.getLower(null)) + LFeature } override val u: Matrix by lazy { - EjmlMatrix(SimpleMatrix(lup.getUpper(null))) + UFeature + EjmlDoubleMatrix(lup.getUpper(null)) + UFeature } - override val p: Matrix by lazy { EjmlMatrix(SimpleMatrix(lup.getRowPivot(null))) } + override val p: Matrix by lazy { EjmlDoubleMatrix(lup.getRowPivot(null)) } } else -> null }?.let(type::cast) } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for 'x' that is n by p. + */ + public fun solve(a: Matrix, b: Matrix): EjmlDoubleMatrix { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res) + return EjmlDoubleMatrix(res) + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for 'x' that is n by p. + */ + public fun solve(a: Matrix, b: Point): EjmlDoubleVector { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res) + return EjmlDoubleVector(res) + } } - -/** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p matrix. - * @return the solution for 'x' that is n by p. - * @author Iaroslav Postovalov - */ -public fun EjmlLinearSpace.solve(a: Matrix, b: Matrix): EjmlMatrix = - EjmlMatrix(a.toEjml().origin.solve(b.toEjml().origin)) - -/** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p vector. - * @return the solution for 'x' that is n by p. - * @author Iaroslav Postovalov - */ -public fun EjmlLinearSpace.solve(a: Matrix, b: Point): EjmlVector = - EjmlVector(a.toEjml().origin.solve(b.toEjml().origin)) - -/** - * Inverts this matrix. - * - * @author Alexander Nozik - */ -@OptIn(UnstableKMathAPI::class) -public fun EjmlMatrix.inverted(): EjmlMatrix = getFeature>()!!.inverse as EjmlMatrix - -/** - * Inverts the given matrix. - * - * @author Alexander Nozik - */ -public fun EjmlLinearSpace.inverse(matrix: Matrix): Matrix = matrix.toEjml().inverted() \ No newline at end of file diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index 32907d199..92c4d1cf0 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -5,18 +5,28 @@ package space.kscience.kmath.ejml -import org.ejml.simple.SimpleMatrix -import space.kscience.kmath.linear.Matrix +import org.ejml.data.DMatrix +import org.ejml.data.Matrix +import space.kscience.kmath.nd.Structure2D /** - * The matrix implementation over EJML [SimpleMatrix]. + * [space.kscience.kmath.linear.Matrix] implementation based on EJML [Matrix]. * - * @property origin the underlying [SimpleMatrix]. + * @param T the type of elements contained in the buffer. + * @param M the type of EJML matrix. + * @property origin The underlying EJML matrix. * @author Iaroslav Postovalov */ -public class EjmlMatrix(public val origin: SimpleMatrix) : Matrix { - public override val rowNum: Int get() = origin.numRows() - public override val colNum: Int get() = origin.numCols() +public abstract class EjmlMatrix(public open val origin: M) : Structure2D { + public override val rowNum: Int get() = origin.numRows + public override val colNum: Int get() = origin.numCols +} +/** + * [EjmlMatrix] specialization for [Double]. + * + * @author Iaroslav Postovalov + */ +public class EjmlDoubleMatrix(public override val origin: M) : EjmlMatrix(origin) { public override operator fun get(i: Int, j: Int): Double = origin[i, j] } diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt index 2f4b4a8e2..81502d6d0 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt @@ -5,35 +5,41 @@ package space.kscience.kmath.ejml -import org.ejml.simple.SimpleMatrix +import org.ejml.data.DMatrixD1 +import org.ejml.data.Matrix import space.kscience.kmath.linear.Point /** - * Represents point over EJML [SimpleMatrix]. + * [Point] implementation based on EJML [Matrix]. * - * @property origin the underlying [SimpleMatrix]. + * @param T the type of elements contained in the buffer. + * @param M the type of EJML matrix. + * @property origin The underlying matrix. * @author Iaroslav Postovalov */ -public class EjmlVector internal constructor(public val origin: SimpleMatrix) : Point { +public abstract class EjmlVector(public open val origin: M) : Point { public override val size: Int - get() = origin.numRows() + get() = origin.numRows - init { - require(origin.numCols() == 1) { "Only single column matrices are allowed" } - } - - public override operator fun get(index: Int): Double = origin[index] - - public override operator fun iterator(): Iterator = object : Iterator { + public override operator fun iterator(): Iterator = object : Iterator { private var cursor: Int = 0 - override fun next(): Double { + override fun next(): T { cursor += 1 - return origin[cursor - 1] + return this@EjmlVector[cursor - 1] } - override fun hasNext(): Boolean = cursor < origin.numCols() * origin.numRows() + override fun hasNext(): Boolean = cursor < origin.numCols * origin.numRows } public override fun toString(): String = "EjmlVector(origin=$origin)" } + +/** + * [EjmlVector] specialization for [Double]. + * + * @author Iaroslav Postovalov + */ +public class EjmlDoubleVector(public override val origin: M) : EjmlVector(origin) { + public override operator fun get(index: Int): Double = origin[index] +} diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt index 59f9602d6..485c53c38 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -5,12 +5,15 @@ package space.kscience.kmath.ejml +import org.ejml.data.DMatrixRMaj +import org.ejml.dense.row.CommonOps_DDRM +import org.ejml.dense.row.RandomMatrices_DDRM import org.ejml.dense.row.factory.DecompositionFactory_DDRM -import org.ejml.simple.SimpleMatrix -import space.kscience.kmath.linear.* +import space.kscience.kmath.linear.DeterminantFeature +import space.kscience.kmath.linear.LupDecompositionFeature +import space.kscience.kmath.linear.getFeature import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND -import space.kscience.kmath.nd.getFeature import kotlin.random.Random import kotlin.random.asJavaRandom import kotlin.test.* @@ -22,65 +25,59 @@ fun assertMatrixEquals(expected: StructureND, actual: StructureND = EjmlLinearSpace.getFeature(w) ?: fail() - assertEquals(m.determinant(), det.determinant) - val lup: LupDecompositionFeature = EjmlLinearSpace.getFeature(w) ?: fail() + val w = EjmlDoubleMatrix(m) + val det: DeterminantFeature = EjmlLinearSpaceDDRM.getFeature(w) ?: fail() + assertEquals(CommonOps_DDRM.det(m), det.determinant) + val lup: LupDecompositionFeature = EjmlLinearSpaceDDRM.getFeature(w) ?: fail() - val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows(), m.numCols()) - .also { it.decompose(m.ddrm.copy()) } + val ludecompositionF64 = DecompositionFactory_DDRM.lu(m.numRows, m.numCols) + .also { it.decompose(m.copy()) } - assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getLower(null))), lup.l) - assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getUpper(null))), lup.u) - assertMatrixEquals(EjmlMatrix(SimpleMatrix(ludecompositionF64.getRowPivot(null))), lup.p) - } - - private object SomeFeature : MatrixFeature {} - - @OptIn(UnstableKMathAPI::class) - @Test - fun suggestFeature() { - assertNotNull((EjmlMatrix(randomMatrix) + SomeFeature).getFeature()) + assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getLower(null)), lup.l) + assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getUpper(null)), lup.u) + assertMatrixEquals(EjmlDoubleMatrix(ludecompositionF64.getRowPivot(null)), lup.p) } @Test fun get() { val m = randomMatrix - assertEquals(m[0, 0], EjmlMatrix(m)[0, 0]) + assertEquals(m[0, 0], EjmlDoubleMatrix(m)[0, 0]) } @Test fun origin() { val m = randomMatrix - assertSame(m, EjmlMatrix(m).origin) + assertSame(m, EjmlDoubleMatrix(m).origin) } } diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt index e1bcd269e..9bf76033d 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt @@ -5,7 +5,8 @@ package space.kscience.kmath.ejml -import org.ejml.simple.SimpleMatrix +import org.ejml.data.DMatrixRMaj +import org.ejml.dense.row.RandomMatrices_DDRM import kotlin.random.Random import kotlin.random.asJavaRandom import kotlin.test.Test @@ -15,30 +16,34 @@ import kotlin.test.assertSame internal class EjmlVectorTest { private val random = Random(0) - private val randomMatrix: SimpleMatrix - get() = SimpleMatrix.random_DDRM(random.nextInt(2, 100), 1, 0.0, 10.0, random.asJavaRandom()) + private val randomMatrix: DMatrixRMaj + get() { + val d = DMatrixRMaj(random.nextInt(2, 100), 1) + RandomMatrices_DDRM.fillUniform(d, random.asJavaRandom()) + return d + } @Test fun size() { val m = randomMatrix - val w = EjmlVector(m) - assertEquals(m.numRows(), w.size) + val w = EjmlDoubleVector(m) + assertEquals(m.numRows, w.size) } @Test fun get() { val m = randomMatrix - val w = EjmlVector(m) + val w = EjmlDoubleVector(m) assertEquals(m[0, 0], w[0]) } @Test fun iterator() { val m = randomMatrix - val w = EjmlVector(m) + val w = EjmlDoubleVector(m) assertEquals( - m.iterator(true, 0, 0, m.numRows() - 1, 0).asSequence().toList(), + m.iterator(true, 0, 0, m.numRows - 1, 0).asSequence().toList(), w.iterator().asSequence().toList() ) } @@ -46,7 +51,7 @@ internal class EjmlVectorTest { @Test fun origin() { val m = randomMatrix - val w = EjmlVector(m) + val w = EjmlDoubleVector(m) assertSame(m, w.origin) } } diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 20e52deb2..46bf657c3 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -15,7 +15,6 @@ The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-d ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap } @@ -28,7 +27,6 @@ dependencies { repositories { maven("https://repo.kotlin.link") maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a } dependencies { diff --git a/kmath-functions/README.md b/kmath-functions/README.md index d5907f1c5..c7c30f1a1 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -17,7 +17,6 @@ The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0- ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap } @@ -30,7 +29,6 @@ dependencies { repositories { maven("https://repo.kotlin.link") maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a } dependencies { diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index f627beec9..ed5b5bcb4 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -4,8 +4,8 @@ plugins { } dependencies { - implementation("com.github.breandan:kaliningraph:0.1.4") - implementation("com.github.breandan:kotlingrad:0.4.0") + api("com.github.breandan:kaliningraph:0.1.4") + api("com.github.breandan:kotlingrad:0.4.5") api(project(":kmath-ast")) } diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 66e0483a4..b4b586ea9 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -15,8 +15,7 @@ The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-7 ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -27,8 +26,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 232bd1388..2e932b441 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -7,9 +7,9 @@ description = "Binding for https://github.com/JetBrains-Research/viktor" dependencies { api(project(":kmath-core")) - api("org.jetbrains.bio:viktor:1.0.1") + api("org.jetbrains.bio:viktor:1.1.0") } readme { maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT -} \ No newline at end of file +} From 2aed0316f4a38f32ed53e2895d6d7f5a74c779f5 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 30 Apr 2021 20:28:55 +0700 Subject: [PATCH 257/393] Use GraalVM as CI JDK --- .github/workflows/build.yml | 6 ++++-- .github/workflows/pages.yml | 6 ++++-- .github/workflows/publish.yml | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f39e12a12..9a9f04621 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,9 +13,11 @@ jobs: - name: Checkout the repo uses: actions/checkout@v2 - name: Set up JDK 11 - uses: actions/setup-java@v1 + uses: DeLaGuardo/setup-graalvm@4.0 with: - java-version: 11 + graalvm: 21.1.0 + java: java11 + arch: amd64 - name: Add msys to path if: matrix.os == 'windows-latest' run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index c70227fce..5892b3c4c 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -12,9 +12,11 @@ jobs: - name: Checkout the repo uses: actions/checkout@v2 - name: Set up JDK 11 - uses: actions/setup-java@v1 + uses: DeLaGuardo/setup-graalvm@4.0 with: - java-version: 11 + graalvm: 21.1.0 + java: java11 + arch: amd64 - name: Cache gradle uses: actions/cache@v2 with: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ca374574e..c5c110e89 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,9 +18,11 @@ jobs: - name: Checkout the repo uses: actions/checkout@v2 - name: Set up JDK 11 - uses: actions/setup-java@v1 + uses: DeLaGuardo/setup-graalvm@4.0 with: - java-version: 11 + graalvm: 21.1.0 + java: java11 + arch: amd64 - name: Add msys to path if: matrix.os == 'windows-latest' run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" From e5e62bc544143ef4f341257c7d143a5b8a813656 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 14:38:03 +0100 Subject: [PATCH 258/393] Extending from Algebra --- .../kmath/tensors/api/TensorAlgebra.kt | 4 ++- .../algebras/BroadcastDoubleTensorAlgebra.kt | 3 +- .../algebras/DoubleAnalyticTensorAlgebra.kt | 10 ++----- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 12 +++----- .../core/algebras/DoubleTensorAlgebra.kt | 5 +--- .../kmath/tensors/core/broadcastUtils.kt | 4 --- .../kscience/kmath/tensors/core/linUtils.kt | 3 +- .../kmath/tensors/core/TestBroadcasting.kt | 16 ++++++----- .../core/TestDoubleAnalyticTensorAlgebra.kt | 5 ++-- .../core/TestDoubleLinearOpsAlgebra.kt | 28 +++++++++---------- .../kmath/tensors/core/TestDoubleTensor.kt | 9 +++--- .../tensors/core/TestDoubleTensorAlgebra.kt | 21 +++++++------- 12 files changed, 56 insertions(+), 64 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 338064231..96d6985d8 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -5,13 +5,15 @@ package space.kscience.kmath.tensors.api +import space.kscience.kmath.operations.Algebra + /** * Algebra over a ring on [TensorStructure]. * For more information: https://proofwiki.org/wiki/Definition:Algebra_over_Ring * * @param T the type of items in the tensors. */ -public interface TensorAlgebra { +public interface TensorAlgebra: Algebra> { /** * Returns a single tensor value of unit dimension. The tensor shape must be equal to [1]. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt index a49d9ab29..fa64092d6 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -14,7 +14,7 @@ import space.kscience.kmath.tensors.core.broadcastTo * Basic linear algebra operations implemented with broadcasting. * For more information: https://pytorch.org/docs/stable/notes/broadcasting.html */ -public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { +public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { val broadcast = broadcastTensors(tensor, other.tensor) @@ -89,5 +89,4 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { newOther.buffer.array()[tensor.bufferStart + i] } } - } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 7d1cceb15..4a942df84 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -11,10 +11,9 @@ import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.tensor import kotlin.math.* -public class DoubleAnalyticTensorAlgebra: +public object DoubleAnalyticTensorAlgebra : AnalyticTensorAlgebra, - DoubleTensorAlgebra() -{ + DoubleTensorAlgebra() { override fun TensorStructure.exp(): DoubleTensor = tensor.map(::exp) override fun TensorStructure.log(): DoubleTensor = tensor.map(::ln) @@ -49,7 +48,4 @@ public class DoubleAnalyticTensorAlgebra: override fun TensorStructure.floor(): DoubleTensor = tensor.map(::floor) -} - -public inline fun DoubleAnalyticTensorAlgebra(block: DoubleAnalyticTensorAlgebra.() -> R): R = - DoubleAnalyticTensorAlgebra().block() \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 03f383728..975755656 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -21,7 +21,7 @@ import space.kscience.kmath.tensors.core.pivInit import kotlin.math.min -public class DoubleLinearOpsTensorAlgebra : +public object DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, DoubleTensorAlgebra() { @@ -30,8 +30,8 @@ public class DoubleLinearOpsTensorAlgebra : override fun TensorStructure.det(): DoubleTensor = detLU(1e-9) public fun TensorStructure.luFactor(epsilon: Double): Pair = - computeLU(tensor, epsilon) ?: - throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon") + computeLU(tensor, epsilon) + ?: throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon") public fun TensorStructure.luFactor(): Pair = luFactor(1e-9) @@ -175,8 +175,4 @@ public class DoubleLinearOpsTensorAlgebra : override fun TensorStructure.lu(): Triple = lu(1e-9) - -} - -public inline fun DoubleLinearOpsTensorAlgebra(block: DoubleLinearOpsTensorAlgebra.() -> R): R = - DoubleLinearOpsTensorAlgebra().block() \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 7414a4469..8729358cc 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -23,6 +23,7 @@ import kotlin.math.abs public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { + public companion object : DoubleTensorAlgebra() override fun TensorStructure.value(): Double { check(tensor.shape contentEquals intArrayOf(1)) { @@ -395,7 +396,3 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) } - - -public inline fun DoubleTensorAlgebra(block: DoubleTensorAlgebra.() -> R): R = - DoubleTensorAlgebra().block() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt index 4378e9ac9..71ccbf97b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt @@ -1,11 +1,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra import kotlin.math.max -public inline fun BroadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorAlgebra.() -> R): R = - BroadcastDoubleTensorAlgebra().block() - internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) { for (linearIndex in 0 until linearSize) { val totalMultiIndex = resTensor.linearStructure.index(linearIndex) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt index 3a130c71e..c7a730018 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt @@ -4,6 +4,7 @@ import space.kscience.kmath.nd.MutableStructure1D import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra import kotlin.math.abs @@ -251,7 +252,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper( } } } - r[j, j] = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + r[j, j] = DoubleAnalyticTensorAlgebra.invoke { (v dot v).sqrt().value() } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index d677f6966..207dd1c98 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -1,13 +1,15 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.test.Test import kotlin.test.assertTrue -class TestBroadcasting { +internal class TestBroadcasting { @Test - fun broadcastShapes() = DoubleTensorAlgebra { + fun broadcastShapes() = DoubleTensorAlgebra.invoke { assertTrue( broadcastShapes( intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) @@ -22,7 +24,7 @@ class TestBroadcasting { } @Test - fun broadcastTo() = DoubleTensorAlgebra { + fun broadcastTo() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) @@ -32,7 +34,7 @@ class TestBroadcasting { } @Test - fun broadcastTensors() = DoubleTensorAlgebra { + fun broadcastTensors() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -49,7 +51,7 @@ class TestBroadcasting { } @Test - fun broadcastOuterTensors() = DoubleTensorAlgebra { + fun broadcastOuterTensors() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -66,7 +68,7 @@ class TestBroadcasting { } @Test - fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra { + fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) {0.0}) val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) {0.0}) val tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0)) @@ -79,7 +81,7 @@ class TestBroadcasting { } @Test - fun minusTensor() = BroadcastDoubleTensorAlgebra { + fun minusTensor() = BroadcastDoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 060bc1607..3b3e22acc 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -1,12 +1,13 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import kotlin.math.abs import kotlin.math.exp import kotlin.test.Test import kotlin.test.assertTrue -class TestDoubleAnalyticTensorAlgebra { +internal class TestDoubleAnalyticTensorAlgebra { val shape = intArrayOf(2, 1, 3, 2) val buffer = doubleArrayOf(27.1, 20.0, 19.84, 23.123, 0.0, 1.0, 3.23, 133.7, 25.3, 100.3, 11.0, 12.012) @@ -26,7 +27,7 @@ class TestDoubleAnalyticTensorAlgebra { } @Test - fun testExp() = DoubleAnalyticTensorAlgebra { + fun testExp() = DoubleAnalyticTensorAlgebra.invoke { tensor.exp().let { assertTrue { shape contentEquals it.shape } assertTrue { buffer.fmap(::exp).epsEqual(it.buffer.array())} diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index b2ef6b4c4..aa68340d4 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -1,15 +1,16 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra import kotlin.math.abs import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue -class TestDoubleLinearOpsTensorAlgebra { +internal class TestDoubleLinearOpsTensorAlgebra { @Test - fun testDetLU() = DoubleLinearOpsTensorAlgebra { + fun testDetLU() = DoubleLinearOpsTensorAlgebra.invoke { val tensor = fromArray( intArrayOf(2, 2, 2), doubleArrayOf( @@ -34,7 +35,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testDet() = DoubleLinearOpsTensorAlgebra { + fun testDet() = DoubleLinearOpsTensorAlgebra.invoke { val expectedValue = 0.019827417 val m = fromArray( intArrayOf(3, 3), doubleArrayOf( @@ -48,7 +49,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testDetSingle() = DoubleLinearOpsTensorAlgebra { + fun testDetSingle() = DoubleLinearOpsTensorAlgebra.invoke { val expectedValue = 48.151623 val m = fromArray( intArrayOf(1, 1), doubleArrayOf( @@ -60,7 +61,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testInvLU() = DoubleLinearOpsTensorAlgebra { + fun testInvLU() = DoubleLinearOpsTensorAlgebra.invoke { val tensor = fromArray( intArrayOf(2, 2, 2), doubleArrayOf( @@ -85,14 +86,14 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testScalarProduct() = DoubleLinearOpsTensorAlgebra { + fun testScalarProduct() = DoubleLinearOpsTensorAlgebra.invoke { val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) assertEquals(a.dot(b).value(), 59.92) } @Test - fun testQR() = DoubleLinearOpsTensorAlgebra { + fun testQR() = DoubleLinearOpsTensorAlgebra.invoke { val shape = intArrayOf(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, @@ -110,11 +111,10 @@ class TestDoubleLinearOpsTensorAlgebra { assertTrue((q dot r).eq(tensor)) - //todo check orthogonality/upper triang. } @Test - fun testLU() = DoubleLinearOpsTensorAlgebra { + fun testLU() = DoubleLinearOpsTensorAlgebra.invoke { val shape = intArrayOf(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, @@ -134,7 +134,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testCholesky() = DoubleLinearOpsTensorAlgebra { + fun testCholesky() = DoubleLinearOpsTensorAlgebra.invoke { val tensor = randNormal(intArrayOf(2, 5, 5), 0) val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) @@ -145,7 +145,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testSVD1D() = DoubleLinearOpsTensorAlgebra { + fun testSVD1D() = DoubleLinearOpsTensorAlgebra.invoke { val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = svd1d(tensor2) @@ -156,13 +156,13 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testSVD() = DoubleLinearOpsTensorAlgebra { + fun testSVD() = DoubleLinearOpsTensorAlgebra.invoke{ testSVDFor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } @Test - fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { + fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra.invoke { val tensor = randNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) @@ -170,7 +170,7 @@ class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { + fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra.invoke { val tensor = randNormal(shape = intArrayOf(2, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 7103eafaa..20acc0901 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -4,6 +4,7 @@ import space.kscience.kmath.nd.DefaultStrides import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asMutableBuffer import space.kscience.kmath.structures.toDoubleArray @@ -12,17 +13,17 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue -class TestDoubleTensor { +internal class TestDoubleTensor { @Test - fun valueTest() = DoubleTensorAlgebra { + fun valueTest() = DoubleTensorAlgebra.invoke { val value = 12.5 val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @Test - fun stridesTest() = DoubleTensorAlgebra { + fun stridesTest() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) assertEquals(tensor[intArrayOf(0, 1)], 5.8) assertTrue( @@ -31,7 +32,7 @@ class TestDoubleTensor { } @Test - fun getTest() = DoubleTensorAlgebra { + fun getTest() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) val matrix = tensor[0].as2D() assertEquals(matrix[0, 1], 5.8) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 1333a7a1f..115016974 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -1,29 +1,30 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.test.Test import kotlin.test.assertFalse import kotlin.test.assertTrue -class TestDoubleTensorAlgebra { +internal class TestDoubleTensorAlgebra { @Test - fun doublePlus() = DoubleTensorAlgebra { + fun doublePlus() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0, 12.0)) } @Test - fun doubleDiv() = DoubleTensorAlgebra { + fun doubleDiv() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0)) val res = 2.0/tensor assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 0.5)) } @Test - fun divDouble() = DoubleTensorAlgebra { + fun divDouble() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0)) val res = tensor / 2.5 assertTrue(res.buffer.array() contentEquals doubleArrayOf(4.0, 2.0)) @@ -39,7 +40,7 @@ class TestDoubleTensorAlgebra { } @Test - fun transpose3x2() = DoubleTensorAlgebra { + fun transpose3x2() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) @@ -48,7 +49,7 @@ class TestDoubleTensorAlgebra { } @Test - fun transpose1x2x3() = DoubleTensorAlgebra { + fun transpose1x2x3() = DoubleTensorAlgebra.invoke { val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transpose(0, 1) val res02 = tensor.transpose(-3, 2) @@ -64,7 +65,7 @@ class TestDoubleTensorAlgebra { } @Test - fun linearStructure() = DoubleTensorAlgebra { + fun linearStructure() = DoubleTensorAlgebra.invoke { val shape = intArrayOf(3) val tensorA = full(value = -4.5, shape = shape) val tensorB = full(value = 10.9, shape = shape) @@ -96,7 +97,7 @@ class TestDoubleTensorAlgebra { } @Test - fun dot() = DoubleTensorAlgebra { + fun dot() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor11 = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) @@ -132,7 +133,7 @@ class TestDoubleTensorAlgebra { } @Test - fun diagonalEmbedding() = DoubleTensorAlgebra { + fun diagonalEmbedding() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = zeros(intArrayOf(2, 3, 4, 5)) @@ -165,7 +166,7 @@ class TestDoubleTensorAlgebra { } @Test - fun testEq() = DoubleTensorAlgebra { + fun testEq() = DoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) From 6be5caa93f4086e222677a55d15edaca707b16f0 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 14:44:42 +0100 Subject: [PATCH 259/393] No secondary constructors --- .../kmath/tensors/core/BufferedTensor.kt | 25 +++---- .../algebras/BroadcastDoubleTensorAlgebra.kt | 28 ++++---- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 2 +- .../core/algebras/DoubleTensorAlgebra.kt | 68 +++++++++---------- .../kmath/tensors/core/broadcastUtils.kt | 10 +-- .../kscience/kmath/tensors/core/linUtils.kt | 14 ++-- .../kmath/tensors/core/TestBroadcasting.kt | 20 +++--- .../core/TestDoubleAnalyticTensorAlgebra.kt | 2 +- .../core/TestDoubleLinearOpsAlgebra.kt | 4 +- .../kmath/tensors/core/TestDoubleTensor.kt | 5 +- .../tensors/core/TestDoubleTensorAlgebra.kt | 34 +++++----- 11 files changed, 103 insertions(+), 109 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 6e1cab11a..fae59804d 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -8,7 +8,7 @@ import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure public open class BufferedTensor( override val shape: IntArray, - internal val buffer: MutableBuffer, + internal val mutableBuffer: MutableBuffer, internal val bufferStart: Int ) : TensorStructure { public val linearStructure: TensorLinearStructure @@ -17,10 +17,10 @@ public open class BufferedTensor( public val numElements: Int get() = linearStructure.size - override fun get(index: IntArray): T = buffer[bufferStart + linearStructure.offset(index)] + override fun get(index: IntArray): T = mutableBuffer[bufferStart + linearStructure.offset(index)] override fun set(index: IntArray, value: T) { - buffer[bufferStart + linearStructure.offset(index)] = value + mutableBuffer[bufferStart + linearStructure.offset(index)] = value } override fun elements(): Sequence> = linearStructure.indices().map { @@ -37,33 +37,28 @@ public class IntTensor internal constructor( shape: IntArray, buffer: IntArray, offset: Int = 0 -) : BufferedTensor(shape, IntBuffer(buffer), offset) { - internal constructor(bufferedTensor: BufferedTensor) : - this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) -} +) : BufferedTensor(shape, IntBuffer(buffer), offset) public class DoubleTensor internal constructor( shape: IntArray, buffer: DoubleArray, offset: Int = 0 ) : BufferedTensor(shape, DoubleBuffer(buffer), offset) { - internal constructor(bufferedTensor: BufferedTensor) : - this(bufferedTensor.shape, bufferedTensor.buffer.array(), bufferedTensor.bufferStart) - override fun toString(): String = toPrettyString() - } -internal inline fun BufferedTensor.asTensor(): IntTensor = IntTensor(this) -internal inline fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this) +internal fun BufferedTensor.asTensor(): IntTensor = + IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) +internal fun BufferedTensor.asTensor(): DoubleTensor = + DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) -internal inline fun TensorStructure.copyToBufferedTensor(): BufferedTensor = +internal fun TensorStructure.copyToBufferedTensor(): BufferedTensor = BufferedTensor( this.shape, TensorLinearStructure(this.shape).indices().map(this::get).toMutableList().asMutableBuffer(), 0 ) -internal inline fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { +internal fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { is BufferedTensor -> this is MutableBufferND -> if (this.strides.strides.toIntArray() contentEquals TensorLinearStructure(this.shape).strides) BufferedTensor(this.shape, this.mutableBuffer, 0) else this.copyToBufferedTensor() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt index fa64092d6..350d939af 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -21,7 +21,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[i] + newOther.buffer.array()[i] + newThis.mutableBuffer.array()[i] + newOther.mutableBuffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -29,8 +29,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.plusAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] += - newOther.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] += + newOther.mutableBuffer.array()[tensor.bufferStart + i] } } @@ -39,7 +39,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[i] - newOther.buffer.array()[i] + newThis.mutableBuffer.array()[i] - newOther.mutableBuffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -47,8 +47,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.minusAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] -= - newOther.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] -= + newOther.mutableBuffer.array()[tensor.bufferStart + i] } } @@ -57,8 +57,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[newThis.bufferStart + i] * - newOther.buffer.array()[newOther.bufferStart + i] + newThis.mutableBuffer.array()[newThis.bufferStart + i] * + newOther.mutableBuffer.array()[newOther.bufferStart + i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -66,8 +66,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.timesAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] *= - newOther.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] *= + newOther.mutableBuffer.array()[tensor.bufferStart + i] } } @@ -76,8 +76,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> - newThis.buffer.array()[newOther.bufferStart + i] / - newOther.buffer.array()[newOther.bufferStart + i] + newThis.mutableBuffer.array()[newOther.bufferStart + i] / + newOther.mutableBuffer.array()[newOther.bufferStart + i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -85,8 +85,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.divAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.size) { - tensor.buffer.array()[tensor.bufferStart + i] /= - newOther.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] /= + newOther.mutableBuffer.array()[tensor.bufferStart + i] } } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 975755656..ab73b25b1 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -106,7 +106,7 @@ public object DoubleLinearOpsTensorAlgebra : val matrixSize = matrix.shape.reduce { acc, i -> acc * i } val curMatrix = DoubleTensor( matrix.shape, - matrix.buffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize).toDoubleArray() + matrix.mutableBuffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize).toDoubleArray() ) svdHelper(curMatrix, USV, m, n, epsilon) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 8729358cc..f428b9d2e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -29,7 +29,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { check(tensor.shape contentEquals intArrayOf(1)) { "Inconsistent value for tensor of shape ${shape.toList()}" } - return tensor.buffer.array()[tensor.bufferStart] + return tensor.mutableBuffer.array()[tensor.bufferStart] } public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor { @@ -43,7 +43,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { val lastShape = tensor.shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) val newStart = newShape.reduce(Int::times) * i + tensor.bufferStart - return DoubleTensor(newShape, tensor.buffer.array(), newStart) + return DoubleTensor(newShape, tensor.mutableBuffer.array(), newStart) } public fun full(value: Double, shape: IntArray): DoubleTensor { @@ -77,12 +77,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } public fun TensorStructure.copy(): DoubleTensor { - return DoubleTensor(tensor.shape, tensor.buffer.array().copyOf(), tensor.bufferStart) + return DoubleTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart) } override fun Double.plus(other: TensorStructure): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> - other.tensor.buffer.array()[other.tensor.bufferStart + i] + this + other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] + this } return DoubleTensor(other.shape, resBuffer) } @@ -92,35 +92,35 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { checkShapesCompatible(tensor, other.tensor) val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[i] + other.tensor.buffer.array()[i] + tensor.mutableBuffer.array()[i] + other.tensor.mutableBuffer.array()[i] } return DoubleTensor(tensor.shape, resBuffer) } override fun TensorStructure.plusAssign(value: Double) { for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] += value + tensor.mutableBuffer.array()[tensor.bufferStart + i] += value } } override fun TensorStructure.plusAssign(other: TensorStructure) { checkShapesCompatible(tensor, other.tensor) for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] += - other.tensor.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] += + other.tensor.mutableBuffer.array()[tensor.bufferStart + i] } } override fun Double.minus(other: TensorStructure): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> - this - other.tensor.buffer.array()[other.tensor.bufferStart + i] + this - other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } override fun TensorStructure.minus(value: Double): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[tensor.bufferStart + i] - value + tensor.mutableBuffer.array()[tensor.bufferStart + i] - value } return DoubleTensor(tensor.shape, resBuffer) } @@ -128,28 +128,28 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[i] - other.tensor.buffer.array()[i] + tensor.mutableBuffer.array()[i] - other.tensor.mutableBuffer.array()[i] } return DoubleTensor(tensor.shape, resBuffer) } override fun TensorStructure.minusAssign(value: Double) { for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] -= value + tensor.mutableBuffer.array()[tensor.bufferStart + i] -= value } } override fun TensorStructure.minusAssign(other: TensorStructure) { checkShapesCompatible(tensor, other) for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] -= - other.tensor.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] -= + other.tensor.mutableBuffer.array()[tensor.bufferStart + i] } } override fun Double.times(other: TensorStructure): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> - other.tensor.buffer.array()[other.tensor.bufferStart + i] * this + other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) } @@ -159,36 +159,36 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun TensorStructure.times(other: TensorStructure): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[tensor.bufferStart + i] * - other.tensor.buffer.array()[other.tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] * + other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(tensor.shape, resBuffer) } override fun TensorStructure.timesAssign(value: Double) { for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] *= value + tensor.mutableBuffer.array()[tensor.bufferStart + i] *= value } } override fun TensorStructure.timesAssign(other: TensorStructure) { checkShapesCompatible(tensor, other) for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] *= - other.tensor.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] *= + other.tensor.mutableBuffer.array()[tensor.bufferStart + i] } } override fun Double.div(other: TensorStructure): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> - this / other.tensor.buffer.array()[other.tensor.bufferStart + i] + this / other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } override fun TensorStructure.div(value: Double): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[tensor.bufferStart + i] / value + tensor.mutableBuffer.array()[tensor.bufferStart + i] / value } return DoubleTensor(shape, resBuffer) } @@ -196,29 +196,29 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun TensorStructure.div(other: TensorStructure): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[other.tensor.bufferStart + i] / - other.tensor.buffer.array()[other.tensor.bufferStart + i] + tensor.mutableBuffer.array()[other.tensor.bufferStart + i] / + other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(tensor.shape, resBuffer) } override fun TensorStructure.divAssign(value: Double) { for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] /= value + tensor.mutableBuffer.array()[tensor.bufferStart + i] /= value } } override fun TensorStructure.divAssign(other: TensorStructure) { checkShapesCompatible(tensor, other) for (i in 0 until tensor.numElements) { - tensor.buffer.array()[tensor.bufferStart + i] /= - other.tensor.buffer.array()[tensor.bufferStart + i] + tensor.mutableBuffer.array()[tensor.bufferStart + i] /= + other.tensor.mutableBuffer.array()[tensor.bufferStart + i] } } override fun TensorStructure.unaryMinus(): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.buffer.array()[tensor.bufferStart + i].unaryMinus() + tensor.mutableBuffer.array()[tensor.bufferStart + i].unaryMinus() } return DoubleTensor(tensor.shape, resBuffer) } @@ -241,8 +241,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } val linearIndex = resTensor.linearStructure.offset(newMultiIndex) - resTensor.buffer.array()[linearIndex] = - tensor.buffer.array()[tensor.bufferStart + offset] + resTensor.mutableBuffer.array()[linearIndex] = + tensor.mutableBuffer.array()[tensor.bufferStart + offset] } return resTensor } @@ -250,7 +250,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun TensorStructure.view(shape: IntArray): DoubleTensor { checkView(tensor, shape) - return DoubleTensor(shape, tensor.buffer.array(), tensor.bufferStart) + return DoubleTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart) } override fun TensorStructure.viewAs(other: TensorStructure): DoubleTensor { @@ -259,7 +259,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override infix fun TensorStructure.dot(other: TensorStructure): DoubleTensor { if (tensor.shape.size == 1 && other.shape.size == 1) { - return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.buffer.array().sum())) + return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.mutableBuffer.array().sum())) } var newThis = tensor.copy() @@ -361,7 +361,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun TensorStructure.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( tensor.shape, - tensor.buffer.array().map { transform(it) }.toDoubleArray(), + tensor.mutableBuffer.array().map { transform(it) }.toDoubleArray(), tensor.bufferStart ) } @@ -382,7 +382,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return false } for (i in 0 until n) { - if (!eqFunction(tensor.buffer[tensor.bufferStart + i], other.tensor.buffer[other.tensor.bufferStart + i])) { + if (!eqFunction(tensor.mutableBuffer[tensor.bufferStart + i], other.tensor.mutableBuffer[other.tensor.bufferStart + i])) { return false } } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt index 71ccbf97b..2d4d6f0f7 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt @@ -18,8 +18,8 @@ internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: Doub } val curLinearIndex = tensor.linearStructure.offset(curMultiIndex) - resTensor.buffer.array()[linearIndex] = - tensor.buffer.array()[tensor.bufferStart + curLinearIndex] + resTensor.mutableBuffer.array()[linearIndex] = + tensor.mutableBuffer.array()[tensor.bufferStart + curLinearIndex] } } @@ -113,7 +113,7 @@ internal inline fun broadcastOuterTensors(vararg tensors: DoubleTensor): List BufferedTensor.vectorSequence(): Sequence BufferedTensor.matrixSequence(): Sequence Date: Wed, 31 Mar 2021 19:39:34 +0700 Subject: [PATCH 260/393] Add Jupyter integration --- CHANGELOG.md | 1 + build.gradle.kts | 1 + .../ast/rendering/MathMLSyntaxRenderer.kt | 9 +- kmath-core/api/kmath-core.api | 2 + .../kscience/kmath/expressions/MstAlgebra.kt | 1 + kmath-jupyter/build.gradle.kts | 19 +++ .../kscience/kmath/jupyter/KMathJupyter.kt | 120 ++++++++++++++++++ settings.gradle.kts | 4 + 8 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 kmath-jupyter/build.gradle.kts create mode 100644 kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 4266c5b70..cdc82753c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Multiplatform integration - Integration for any Field element - Extended operations for ND4J fields +- Jupyter Notebook integration module (kmath-jupyter) ### Changed - Exponential operations merged with hyperbolic functions diff --git a/build.gradle.kts b/build.gradle.kts index 506f51a0e..760bf1aee 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("ru.mipt.npm.gradle.project") + kotlin("jupyter.api") apply false } allprojects { diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index 517ec0dc9..5b44e660d 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -18,11 +18,14 @@ import space.kscience.kmath.misc.UnstableKMathAPI public object MathMLSyntaxRenderer : SyntaxRenderer { public override fun render(node: MathSyntax, output: Appendable) { output.append("") - render0(node, output) + renderPart(node, output) output.append("") } - private fun render0(node: MathSyntax, output: Appendable): Unit = output.run { + /** + * Renders a part of syntax returning a correct MathML tag not the whole MathML instance. + */ + public fun renderPart(node: MathSyntax, output: Appendable): Unit = output.run { fun tag(tagName: String, vararg attr: Pair, block: () -> Unit = {}) { append('<') append(tagName) @@ -47,7 +50,7 @@ public object MathMLSyntaxRenderer : SyntaxRenderer { append('>') } - fun render(syntax: MathSyntax) = render0(syntax, output) + fun render(syntax: MathSyntax) = renderPart(syntax, output) when (node) { is NumberSyntax -> tag("mn") { append(node.string) } diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 6b300123c..82b44d275 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -272,6 +272,8 @@ public final class space/kscience/kmath/expressions/MstExtendedField : space/ksc public fun sin (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; + public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; + public fun sqrt (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; public fun tan (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt index 32a7efc1e..53124b777 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt @@ -135,6 +135,7 @@ public object MstExtendedField : ExtendedField, NumericAlgebra { public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ACOSH_OPERATION)(arg) public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ATANH_OPERATION)(arg) public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b) + public override fun sqrt(arg: MST): MST = unaryOperationFunction(PowerOperations.SQRT_OPERATION)(arg) public override fun scale(a: MST, value: Double): MST = binaryOperation(GroupOperations.PLUS_OPERATION, a, number(value)) diff --git a/kmath-jupyter/build.gradle.kts b/kmath-jupyter/build.gradle.kts new file mode 100644 index 000000000..815cb9b8c --- /dev/null +++ b/kmath-jupyter/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + id("ru.mipt.npm.gradle.jvm") + kotlin("jupyter.api") +} + +dependencies { + api(project(":kmath-ast")) + api(project(":kmath-complex")) + api(project(":kmath-for-real")) + implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.3") +} + +readme { + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE +} + +kotlin.sourceSets.all { + languageSettings.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") +} diff --git a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt new file mode 100644 index 000000000..e13c92f75 --- /dev/null +++ b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt @@ -0,0 +1,120 @@ +package space.kscience.kmath.jupyter + +import kotlinx.html.Unsafe +import kotlinx.html.div +import kotlinx.html.stream.createHTML +import kotlinx.html.unsafe +import org.jetbrains.kotlinx.jupyter.api.DisplayResult +import org.jetbrains.kotlinx.jupyter.api.HTML +import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary +import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess +import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer +import space.kscience.kmath.ast.rendering.renderWithStringBuilder +import space.kscience.kmath.complex.Complex +import space.kscience.kmath.nd.Structure2D +import space.kscience.kmath.operations.GroupOperations +import space.kscience.kmath.operations.RingOperations +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asSequence + +@JupyterLibrary +internal class KMathJupyter : JupyterIntegration() { + private val mathRender = FeaturedMathRendererWithPostProcess.Default + private val syntaxRender = MathMLSyntaxRenderer + + override fun Builder.onLoaded() { + import( + "space.kscience.kmath.ast.*", + "space.kscience.kmath.ast.rendering.*", + "space.kscience.kmath.operations.*", + "space.kscience.kmath.expressions.*", + "space.kscience.kmath.misc.*", + "space.kscience.kmath.real.*", + ) + + fun MST.toDisplayResult(): DisplayResult = HTML(createHTML().div { + unsafe { + +syntaxRender.renderWithStringBuilder(mathRender.render(this@toDisplayResult)) + } + }) + + render { it.toDisplayResult() } + render { MST.Numeric(it).toDisplayResult() } + + fun Unsafe.appendCellValue(it: Any?) { + when (it) { + is Number -> { + val s = StringBuilder() + syntaxRender.renderPart(mathRender.render(MST.Numeric(it)), s) + +s.toString() + } + is MST -> { + val s = StringBuilder() + syntaxRender.renderPart(mathRender.render(it), s) + +s.toString() + } + else -> { + +"" + +it.toString() + +"" + } + } + } + + render> { structure -> + HTML(createHTML().div { + unsafe { + +"" + +"" + +"" + +"" + structure.rows.forEach { row -> + +"" + row.asSequence().forEach { + +"" + appendCellValue(it) + +"" + } + +"" + } + +"" + +"" + +"" + +"" + } + }) + } + + render> { buffer -> + HTML(createHTML().div { + unsafe { + +"" + +"" + +"" + +"" + buffer.asSequence().forEach { + +"" + +"" + appendCellValue(it) + +"" + +"" + } + +"" + +"" + +"" + +"" + } + }) + } + + render { + MST.Binary( + operation = GroupOperations.PLUS_OPERATION, + left = MST.Numeric(it.re), + right = MST.Binary(RingOperations.TIMES_OPERATION, MST.Numeric(it.im), MST.Symbolic("i")), + ).toDisplayResult() + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index ca36168e1..b7613d589 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,6 +17,9 @@ pluginManagement { id("ru.mipt.npm.gradle.project") version toolsVersion id("ru.mipt.npm.gradle.mpp") version toolsVersion id("ru.mipt.npm.gradle.jvm") version toolsVersion + kotlin("jupyter.api") version "0.9.0.12" + kotlin("jvm") version kotlinVersion + kotlin("plugin.allopen") version kotlinVersion } } @@ -39,6 +42,7 @@ include( ":kmath-ast", ":kmath-ejml", ":kmath-kotlingrad", + ":kmath-jupyter", ":examples", ":benchmarks" ) From 86c2816cfde632cdb734d18d75e7245e3ae54f0c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 14:53:02 +0100 Subject: [PATCH 261/393] Fixed strides code duplication --- kmath-core/api/kmath-core.api | 4 ++-- .../space/kscience/kmath/nd/StructureND.kt | 6 +++--- .../kmath/tensors/core/BufferedTensor.kt | 4 ++-- .../algebras/BroadcastDoubleTensorAlgebra.kt | 16 +++++++------- .../core/algebras/TensorLinearStructure.kt | 21 ++++++++++--------- 5 files changed, 26 insertions(+), 25 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 41b85b3bb..1b98f547c 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -789,7 +789,7 @@ public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath public fun equals (Ljava/lang/Object;)Z public fun getLinearSize ()I public fun getShape ()[I - public fun getStrides ()Ljava/util/List; + public fun getStrides ()[I public fun hashCode ()I public fun index (I)[I public fun offset ([I)I @@ -931,7 +931,7 @@ public final class space/kscience/kmath/nd/ShortRingNDKt { public abstract interface class space/kscience/kmath/nd/Strides { public abstract fun getLinearSize ()I public abstract fun getShape ()[I - public abstract fun getStrides ()Ljava/util/List; + public abstract fun getStrides ()[I public abstract fun index (I)[I public fun indices ()Lkotlin/sequences/Sequence; public abstract fun offset ([I)I diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index 0656b1f7f..65c233012 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -184,7 +184,7 @@ public interface Strides { /** * Array strides */ - public val strides: List + public val strides: IntArray /** * Get linear index from multidimensional index @@ -221,7 +221,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) : /** * Strides for memory access */ - override val strides: List by lazy { + override val strides: IntArray by lazy { sequence { var current = 1 yield(1) @@ -230,7 +230,7 @@ public class DefaultStrides private constructor(override val shape: IntArray) : current *= it yield(current) } - }.toList() + }.toList().toIntArray() } override fun offset(index: IntArray): Int = index.mapIndexed { i, value -> diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index fae59804d..21030bbc7 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -15,7 +15,7 @@ public open class BufferedTensor( get() = TensorLinearStructure(shape) public val numElements: Int - get() = linearStructure.size + get() = linearStructure.linearSize override fun get(index: IntArray): T = mutableBuffer[bufferStart + linearStructure.offset(index)] @@ -60,7 +60,7 @@ internal fun TensorStructure.copyToBufferedTensor(): BufferedTensor = internal fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { is BufferedTensor -> this - is MutableBufferND -> if (this.strides.strides.toIntArray() contentEquals TensorLinearStructure(this.shape).strides) + is MutableBufferND -> if (this.strides.strides contentEquals TensorLinearStructure(this.shape).strides) BufferedTensor(this.shape, this.mutableBuffer, 0) else this.copyToBufferedTensor() else -> this.copyToBufferedTensor() } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt index 350d939af..9b97d5ef2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -20,7 +20,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.linearSize) { i -> newThis.mutableBuffer.array()[i] + newOther.mutableBuffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) @@ -28,7 +28,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.plusAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { + for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] += newOther.mutableBuffer.array()[tensor.bufferStart + i] } @@ -38,7 +38,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.linearSize) { i -> newThis.mutableBuffer.array()[i] - newOther.mutableBuffer.array()[i] } return DoubleTensor(newThis.shape, resBuffer) @@ -46,7 +46,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.minusAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { + for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] -= newOther.mutableBuffer.array()[tensor.bufferStart + i] } @@ -56,7 +56,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.linearSize) { i -> newThis.mutableBuffer.array()[newThis.bufferStart + i] * newOther.mutableBuffer.array()[newOther.bufferStart + i] } @@ -65,7 +65,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.timesAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { + for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] *= newOther.mutableBuffer.array()[tensor.bufferStart + i] } @@ -75,7 +75,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.linearStructure.size) { i -> + val resBuffer = DoubleArray(newThis.linearStructure.linearSize) { i -> newThis.mutableBuffer.array()[newOther.bufferStart + i] / newOther.mutableBuffer.array()[newOther.bufferStart + i] } @@ -84,7 +84,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun TensorStructure.divAssign(other: TensorStructure) { val newOther = broadcastTo(other.tensor, tensor.shape) - for (i in 0 until tensor.linearStructure.size) { + for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] /= newOther.mutableBuffer.array()[tensor.bufferStart + i] } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index b16739892..8e83dafd6 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -5,16 +5,17 @@ package space.kscience.kmath.tensors.core.algebras +import space.kscience.kmath.nd.Strides import kotlin.math.max -internal inline fun offsetFromIndex(index: IntArray, shape: IntArray, strides: IntArray): Int = +internal fun offsetFromIndex(index: IntArray, shape: IntArray, strides: IntArray): Int = index.mapIndexed { i, value -> if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})") value * strides[i] }.sum() -internal inline fun stridesFromShape(shape: IntArray): IntArray { +internal fun stridesFromShape(shape: IntArray): IntArray { val nDim = shape.size val res = IntArray(nDim) if (nDim == 0) @@ -31,7 +32,7 @@ internal inline fun stridesFromShape(shape: IntArray): IntArray { } -internal inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { +internal fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { val res = IntArray(nDim) var current = offset var strideIndex = 0 @@ -44,7 +45,7 @@ internal inline fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): return res } -internal inline fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { +internal fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { val res = index.copyOf() var current = nDim - 1 var carry = 0 @@ -62,26 +63,26 @@ internal inline fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntA } -public class TensorLinearStructure(public val shape: IntArray) +public class TensorLinearStructure(override val shape: IntArray) : Strides { - public val strides: IntArray + override val strides: IntArray get() = stridesFromShape(shape) - public fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides) + override fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides) - public fun index(offset: Int): IntArray = + override fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) public fun stepIndex(index: IntArray): IntArray = stepIndex(index, shape, shape.size) - public val size: Int + override val linearSize: Int get() = shape.reduce(Int::times) public val dim: Int get() = shape.size - public fun indices(): Sequence = (0 until size).asSequence().map { + override fun indices(): Sequence = (0 until linearSize).asSequence().map { index(it) } } \ No newline at end of file From 42ddd2e5692156ac4263f28fa9848e62180f2b38 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 15:08:32 +0100 Subject: [PATCH 262/393] MutableBufferFromGenerator --- kmath-core/api/kmath-core.api | 18 +++++++++--------- .../space/kscience/kmath/nd/Structure1D.kt | 4 ++-- .../space/kscience/kmath/nd/Structure2D.kt | 6 +++--- .../space/kscience/kmath/structures/Buffer.kt | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 1b98f547c..687de9cc8 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -1882,6 +1882,15 @@ public final class space/kscience/kmath/structures/MutableBuffer$Companion { public final fun short-1yRgbGw (ILkotlin/jvm/functions/Function1;)[S } +public final class space/kscience/kmath/structures/MutableBufferFromGenerator : space/kscience/kmath/structures/MutableBuffer { + public fun (ILkotlin/jvm/functions/Function1;)V + public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun get (I)Ljava/lang/Object; + public fun getSize ()I + public fun iterator ()Ljava/util/Iterator; + public fun set (ILjava/lang/Object;)V +} + public final class space/kscience/kmath/structures/MutableListBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/MutableListBuffer; public static fun constructor-impl (ILkotlin/jvm/functions/Function1;)Ljava/util/List; @@ -1990,12 +1999,3 @@ public final class space/kscience/kmath/structures/VirtualBuffer : space/kscienc public fun iterator ()Ljava/util/Iterator; } -public final class space/kscience/kmath/structures/VirtualMutableBuffer : space/kscience/kmath/structures/MutableBuffer { - public fun (ILkotlin/jvm/functions/Function1;)V - public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; - public fun get (I)Ljava/lang/Object; - public fun getSize ()I - public fun iterator ()Ljava/util/Iterator; - public fun set (ILjava/lang/Object;)V -} - diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 93fc48713..8ea6d0f02 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -52,7 +52,7 @@ private value class Structure1DWrapper(val structure: StructureND) : Struc /** * A 1D wrapper for a mutable nd-structure */ -private inline class MutableStructure1DWrapper(val structure: MutableStructureND) : MutableStructure1D { +private class MutableStructure1DWrapper(val structure: MutableStructureND) : MutableStructure1D { override val shape: IntArray get() = structure.shape override val size: Int get() = structure.shape[0] override fun elements(): Sequence> = structure.elements() @@ -81,7 +81,7 @@ private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D { override operator fun get(index: Int): T = buffer[index] } -internal inline class MutableBuffer1DWrapper(val buffer: MutableBuffer) : MutableStructure1D { +internal class MutableBuffer1DWrapper(val buffer: MutableBuffer) : MutableStructure1D { override val shape: IntArray get() = intArrayOf(buffer.size) override val size: Int get() = buffer.size diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 4c17d25d0..d987d8cf4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.VirtualBuffer -import space.kscience.kmath.structures.VirtualMutableBuffer +import space.kscience.kmath.structures.MutableBufferFromGenerator import kotlin.jvm.JvmInline import kotlin.reflect.KClass @@ -81,13 +81,13 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { * The buffer of rows of this structure. It gets elements from the structure dynamically. */ override val rows: List> - get() = List(rowNum) { i -> MutableBuffer1DWrapper(VirtualMutableBuffer(colNum) { j -> get(i, j) })} + get() = List(rowNum) { i -> MutableBuffer1DWrapper(MutableBufferFromGenerator(colNum) { j -> get(i, j) })} /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ override val columns: List> - get() = List(colNum) { j -> MutableBuffer1DWrapper(VirtualMutableBuffer(rowNum) { i -> get(i, j) }) } + get() = List(colNum) { j -> MutableBuffer1DWrapper(MutableBufferFromGenerator(rowNum) { i -> get(i, j) }) } } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 980fe698e..19018ffb5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -292,7 +292,7 @@ public class VirtualBuffer(override val size: Int, private val generator: (In override operator fun iterator(): Iterator = (0 until size).asSequence().map(generator).iterator() } -public class VirtualMutableBuffer(override val size: Int, private val generator: (Int) -> T) : MutableBuffer { +public class MutableBufferFromGenerator(override val size: Int, private val generator: (Int) -> T) : MutableBuffer { private val bufferHolder: MutableListBuffer = (0 until size).map(generator).toMutableList().asMutableBuffer() From 1695fc5075712c1c89121c0860c7c1e985737dbf Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 15:25:45 +0100 Subject: [PATCH 263/393] Fix examples --- .../space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt | 3 ++- .../src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index 38d8c1437..a84224bcf 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra @@ -13,7 +14,7 @@ import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra fun main () { // work in context with linear operations - DoubleLinearOpsTensorAlgebra { + DoubleLinearOpsTensorAlgebra.invoke { // set true value of x val trueX = fromArray( diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 9318fe928..0408bba63 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra @@ -18,7 +19,7 @@ fun main() { val randSeed = 100500L // work in context with linear operations - DoubleLinearOpsTensorAlgebra { + DoubleLinearOpsTensorAlgebra.invoke { // take coefficient vector from normal distribution val alpha = randNormal( intArrayOf(5), From e2c7751c7eb146641cec0bba6e10e51e849e8371 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 30 Apr 2021 19:45:31 +0300 Subject: [PATCH 264/393] refactor linops --- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index ab73b25b1..700fafbeb 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -53,14 +53,15 @@ public object DoubleLinearOpsTensorAlgebra : val lTensor = luTensor.zeroesLike() val uTensor = luTensor.zeroesLike() - for ((pairLU, lu) in lTensor.matrixSequence().zip(uTensor.matrixSequence()) - .zip(luTensor.tensor.matrixSequence())) { - val (l, u) = pairLU - luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) - } + lTensor.matrixSequence() + .zip(uTensor.matrixSequence()) + .zip(luTensor.tensor.matrixSequence()) + .forEach { (pairLU, lu) -> + val (l, u) = pairLU + luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) + } return Triple(pTensor, lTensor, uTensor) - } public fun TensorStructure.cholesky(epsilon: Double): DoubleTensor { @@ -82,11 +83,13 @@ public object DoubleLinearOpsTensorAlgebra : checkSquareMatrix(shape) val qTensor = zeroesLike() val rTensor = zeroesLike() - val seq = tensor.matrixSequence().zip((qTensor.matrixSequence().zip(rTensor.matrixSequence()))) - for ((matrix, qr) in seq) { + tensor.matrixSequence() + .zip((qTensor.matrixSequence() + .zip(rTensor.matrixSequence()))).forEach { (matrix, qr) -> val (q, r) = qr qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) } + return qTensor to rTensor } @@ -97,20 +100,24 @@ public object DoubleLinearOpsTensorAlgebra : val size = tensor.linearStructure.dim val commonShape = tensor.shape.sliceArray(0 until size - 2) val (n, m) = tensor.shape.sliceArray(size - 2 until size) - val resU = zeros(commonShape + intArrayOf(min(n, m), n)) - val resS = zeros(commonShape + intArrayOf(min(n, m))) - val resV = zeros(commonShape + intArrayOf(min(n, m), m)) + val uTensor = zeros(commonShape + intArrayOf(min(n, m), n)) + val sTensor = zeros(commonShape + intArrayOf(min(n, m))) + val vTensor = zeros(commonShape + intArrayOf(min(n, m), m)) - for ((matrix, USV) in tensor.matrixSequence() - .zip(resU.matrixSequence().zip(resS.vectorSequence().zip(resV.matrixSequence())))) { - val matrixSize = matrix.shape.reduce { acc, i -> acc * i } - val curMatrix = DoubleTensor( - matrix.shape, - matrix.mutableBuffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize).toDoubleArray() - ) - svdHelper(curMatrix, USV, m, n, epsilon) - } - return Triple(resU.transpose(), resS, resV.transpose()) + tensor.matrixSequence() + .zip(uTensor.matrixSequence() + .zip(sTensor.vectorSequence() + .zip(vTensor.matrixSequence()))).forEach { (matrix, USV) -> + val matrixSize = matrix.shape.reduce { acc, i -> acc * i } + val curMatrix = DoubleTensor( + matrix.shape, + matrix.mutableBuffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize) + .toDoubleArray() + ) + svdHelper(curMatrix, USV, m, n, epsilon) + } + + return Triple(uTensor.transpose(), sTensor, vTensor.transpose()) } override fun TensorStructure.symEig(): Pair = @@ -127,7 +134,7 @@ public object DoubleLinearOpsTensorAlgebra : cleanSymHelper(matrix.as2D(), n) val eig = (utv dot s.view(shp)).view(s.shape) - return Pair(eig, v) + return eig to v } public fun TensorStructure.detLU(epsilon: Double = 1e-9): DoubleTensor { From f0cdb9b6571774bd861288f059abaf0571c232bf Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 30 Apr 2021 20:07:59 +0300 Subject: [PATCH 265/393] refactor utils and remove inline --- .../kmath/tensors/core/broadcastUtils.kt | 77 +++++++++---------- .../kscience/kmath/tensors/core/checks.kt | 18 ++--- .../kscience/kmath/tensors/core/linUtils.kt | 41 +++++----- .../kscience/kmath/tensors/core/utils.kt | 45 ++++++----- .../core/TestDoubleLinearOpsAlgebra.kt | 2 +- 5 files changed, 94 insertions(+), 89 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt index 2d4d6f0f7..58d8654af 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.tensors.core import kotlin.math.max -internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) { +internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) { for (linearIndex in 0 until linearSize) { val totalMultiIndex = resTensor.linearStructure.index(linearIndex) val curMultiIndex = tensor.shape.copyOf() @@ -23,7 +23,7 @@ internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: Doub } } -internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { +internal fun broadcastShapes(vararg shapes: IntArray): IntArray { var totalDim = 0 for (shape in shapes) { totalDim = max(totalDim, shape.size) @@ -51,7 +51,7 @@ internal inline fun broadcastShapes(vararg shapes: IntArray): IntArray { return totalShape } -internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor { +internal fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor { if (tensor.shape.size > newShape.size) { throw RuntimeException("Tensor is not compatible with the new shape") } @@ -71,7 +71,7 @@ internal inline fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): Doubl return resTensor } -internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List { +internal fun broadcastTensors(vararg tensors: DoubleTensor): List { val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) val n = totalShape.reduce { acc, i -> acc * i } @@ -85,7 +85,7 @@ internal inline fun broadcastTensors(vararg tensors: DoubleTensor): List { +internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List { val onlyTwoDims = tensors.asSequence().onEach { require(it.shape.size >= 2) { throw RuntimeException("Tensors must have at least 2 dimensions") @@ -99,46 +99,45 @@ internal inline fun broadcastOuterTensors(vararg tensors: DoubleTensor): List acc * i } - val res = ArrayList(0) - for (tensor in tensors) { - val matrixShape = tensor.shape.sliceArray(tensor.shape.size - 2 until tensor.shape.size).copyOf() - val matrixSize = matrixShape[0] * matrixShape[1] - val matrix = DoubleTensor(matrixShape, DoubleArray(matrixSize)) + return buildList { + for (tensor in tensors) { + val matrixShape = tensor.shape.sliceArray(tensor.shape.size - 2 until tensor.shape.size).copyOf() + val matrixSize = matrixShape[0] * matrixShape[1] + val matrix = DoubleTensor(matrixShape, DoubleArray(matrixSize)) - val outerTensor = DoubleTensor(totalShape, DoubleArray(n)) - val resTensor = DoubleTensor(totalShape + matrixShape, DoubleArray(n * matrixSize)) + val outerTensor = DoubleTensor(totalShape, DoubleArray(n)) + val resTensor = DoubleTensor(totalShape + matrixShape, DoubleArray(n * matrixSize)) - for (linearIndex in 0 until n) { - val totalMultiIndex = outerTensor.linearStructure.index(linearIndex) - var curMultiIndex = tensor.shape.sliceArray(0..tensor.shape.size - 3).copyOf() - curMultiIndex = IntArray(totalMultiIndex.size - curMultiIndex.size) { 1 } + curMultiIndex + for (linearIndex in 0 until n) { + val totalMultiIndex = outerTensor.linearStructure.index(linearIndex) + var curMultiIndex = tensor.shape.sliceArray(0..tensor.shape.size - 3).copyOf() + curMultiIndex = IntArray(totalMultiIndex.size - curMultiIndex.size) { 1 } + curMultiIndex - val newTensor = DoubleTensor(curMultiIndex + matrixShape, tensor.mutableBuffer.array()) + val newTensor = DoubleTensor(curMultiIndex + matrixShape, tensor.mutableBuffer.array()) - for (i in curMultiIndex.indices) { - if (curMultiIndex[i] != 1) { - curMultiIndex[i] = totalMultiIndex[i] - } else { - curMultiIndex[i] = 0 + for (i in curMultiIndex.indices) { + if (curMultiIndex[i] != 1) { + curMultiIndex[i] = totalMultiIndex[i] + } else { + curMultiIndex[i] = 0 + } + } + + for (i in 0 until matrixSize) { + val curLinearIndex = newTensor.linearStructure.offset( + curMultiIndex + + matrix.linearStructure.index(i) + ) + val newLinearIndex = resTensor.linearStructure.offset( + totalMultiIndex + + matrix.linearStructure.index(i) + ) + + resTensor.mutableBuffer.array()[resTensor.bufferStart + newLinearIndex] = + newTensor.mutableBuffer.array()[newTensor.bufferStart + curLinearIndex] } } - - for (i in 0 until matrixSize) { - val curLinearIndex = newTensor.linearStructure.offset( - curMultiIndex + - matrix.linearStructure.index(i) - ) - val newLinearIndex = resTensor.linearStructure.offset( - totalMultiIndex + - matrix.linearStructure.index(i) - ) - - resTensor.mutableBuffer.array()[resTensor.bufferStart + newLinearIndex] = - newTensor.mutableBuffer.array()[newTensor.bufferStart + curLinearIndex] - } + add(resTensor) } - res += resTensor } - - return res } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index fd5c8413d..fd98be8b2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -5,38 +5,38 @@ import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra -internal inline fun checkEmptyShape(shape: IntArray): Unit = +internal fun checkEmptyShape(shape: IntArray): Unit = check(shape.isNotEmpty()) { "Illegal empty shape provided" } -internal inline fun checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = +internal fun checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = check(buffer.isNotEmpty()) { "Illegal empty buffer provided" } -internal inline fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = +internal fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = check(buffer.size == shape.reduce(Int::times)) { "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" } -internal inline fun checkShapesCompatible(a: TensorStructure, b: TensorStructure): Unit = +internal fun checkShapesCompatible(a: TensorStructure, b: TensorStructure): Unit = check(a.shape contentEquals b.shape) { "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " } -internal inline fun checkTranspose(dim: Int, i: Int, j: Int): Unit = +internal fun checkTranspose(dim: Int, i: Int, j: Int): Unit = check((i < dim) and (j < dim)) { "Cannot transpose $i to $j for a tensor of dim $dim" } -internal inline fun checkView(a: TensorStructure, shape: IntArray): Unit = +internal fun checkView(a: TensorStructure, shape: IntArray): Unit = check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) -internal inline fun checkSquareMatrix(shape: IntArray): Unit { +internal fun checkSquareMatrix(shape: IntArray): Unit { val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n instead" @@ -46,14 +46,14 @@ internal inline fun checkSquareMatrix(shape: IntArray): Unit { } } -internal inline fun DoubleTensorAlgebra.checkSymmetric( +internal fun DoubleTensorAlgebra.checkSymmetric( tensor: TensorStructure, epsilon: Double = 1e-6 ): Unit = check(tensor.eq(tensor.transpose(), epsilon)) { "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } -internal inline fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( +internal fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( tensor: DoubleTensor, epsilon: Double = 1e-6 ): Unit { checkSymmetric(tensor, epsilon) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt index 776a5e4d5..a152b3a17 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt @@ -13,7 +13,7 @@ import kotlin.math.sign import kotlin.math.sqrt -internal inline fun BufferedTensor.vectorSequence(): Sequence> = sequence { +internal fun BufferedTensor.vectorSequence(): Sequence> = sequence { val n = shape.size val vectorOffset = shape[n - 1] val vectorShape = intArrayOf(shape.last()) @@ -23,9 +23,9 @@ internal inline fun BufferedTensor.vectorSequence(): Sequence BufferedTensor.matrixSequence(): Sequence> = sequence { - check(shape.size >= 2) { "todo" } +internal fun BufferedTensor.matrixSequence(): Sequence> = sequence { val n = shape.size + check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } val matrixOffset = shape[n - 1] * shape[n - 2] val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) for (offset in 0 until numElements step matrixOffset) { @@ -46,8 +46,7 @@ internal inline fun BufferedTensor.forEachMatrix(matrixAction: (BufferedT } } - -internal inline fun dotHelper( +internal fun dotHelper( a: MutableStructure2D, b: MutableStructure2D, res: MutableStructure2D, @@ -64,10 +63,11 @@ internal inline fun dotHelper( } } -internal inline fun luHelper( +internal fun luHelper( lu: MutableStructure2D, pivots: MutableStructure1D, - epsilon: Double): Boolean { + epsilon: Double +): Boolean { val m = lu.rowNum @@ -114,7 +114,7 @@ internal inline fun luHelper( return false } -internal inline fun BufferedTensor.setUpPivots(): IntTensor { +internal fun BufferedTensor.setUpPivots(): IntTensor { val n = this.shape.size val m = this.shape.last() val pivotsShape = IntArray(n - 1) { i -> this.shape[i] } @@ -126,22 +126,23 @@ internal inline fun BufferedTensor.setUpPivots(): IntTensor { ) } -internal inline fun DoubleLinearOpsTensorAlgebra.computeLU( +internal fun DoubleLinearOpsTensorAlgebra.computeLU( tensor: DoubleTensor, - epsilon: Double): Pair? { + epsilon: Double +): Pair? { checkSquareMatrix(tensor.shape) val luTensor = tensor.copy() val pivotsTensor = tensor.setUpPivots() for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) - if(luHelper(lu.as2D(), pivots.as1D(), epsilon)) + if (luHelper(lu.as2D(), pivots.as1D(), epsilon)) return null return Pair(luTensor, pivotsTensor) } -internal inline fun pivInit( +internal fun pivInit( p: MutableStructure2D, pivot: MutableStructure1D, n: Int @@ -151,7 +152,7 @@ internal inline fun pivInit( } } -internal inline fun luPivotHelper( +internal fun luPivotHelper( l: MutableStructure2D, u: MutableStructure2D, lu: MutableStructure2D, @@ -172,7 +173,7 @@ internal inline fun luPivotHelper( } } -internal inline fun choleskyHelper( +internal fun choleskyHelper( a: MutableStructure2D, l: MutableStructure2D, n: Int @@ -193,7 +194,7 @@ internal inline fun choleskyHelper( } } -internal inline fun luMatrixDet(lu: MutableStructure2D, pivots: MutableStructure1D): Double { +internal fun luMatrixDet(lu: MutableStructure2D, pivots: MutableStructure1D): Double { if (lu[0, 0] == 0.0) { return 0.0 } @@ -202,7 +203,7 @@ internal inline fun luMatrixDet(lu: MutableStructure2D, pivots: MutableS return (0 until m).asSequence().map { lu[it, it] }.fold(sign) { left, right -> left * right } } -internal inline fun luMatrixInv( +internal fun luMatrixInv( lu: MutableStructure2D, pivots: MutableStructure1D, invMatrix: MutableStructure2D @@ -229,7 +230,7 @@ internal inline fun luMatrixInv( } } -internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper( +internal fun DoubleLinearOpsTensorAlgebra.qrHelper( matrix: DoubleTensor, q: DoubleTensor, r: MutableStructure2D @@ -259,7 +260,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper( } } -internal inline fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { +internal fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { val (n, m) = a.shape var v: DoubleTensor val b: DoubleTensor @@ -283,7 +284,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: } } -internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( +internal fun DoubleLinearOpsTensorAlgebra.svdHelper( matrix: DoubleTensor, USV: Pair, Pair, BufferedTensor>>, m: Int, n: Int, epsilon: Double @@ -335,7 +336,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.svdHelper( } } -internal inline fun cleanSymHelper(matrix: MutableStructure2D, n: Int) { +internal fun cleanSymHelper(matrix: MutableStructure2D, n: Int) { for (i in 0 until n) for (j in 0 until n) { if (i == j) { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index cb23dbdd6..58d280307 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -23,19 +23,19 @@ internal fun Buffer.array(): DoubleArray = when (this) { else -> this.toDoubleArray() } -internal inline fun getRandomNormals(n: Int, seed: Long): DoubleArray { +internal fun getRandomNormals(n: Int, seed: Long): DoubleArray { val distribution = GaussianSampler(0.0, 1.0) val generator = RandomGenerator.default(seed) return distribution.sample(generator).nextBufferBlocking(n).toDoubleArray() } -internal inline fun getRandomUnitVector(n: Int, seed: Long): DoubleArray { +internal fun getRandomUnitVector(n: Int, seed: Long): DoubleArray { val unnorm = getRandomNormals(n, seed) val norm = sqrt(unnorm.map { it * it }.sum()) return unnorm.map { it / norm }.toDoubleArray() } -internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { +internal fun minusIndexFrom(n: Int, i: Int): Int = if (i >= 0) i else { val ii = n + i check(ii >= 0) { "Out of bound index $i for tensor of dim $n" @@ -43,27 +43,28 @@ internal inline fun minusIndexFrom(n: Int, i: Int) : Int = if (i >= 0) i else { ii } -internal inline fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.dimension, i) +internal fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.dimension, i) -internal inline fun format(value: Double, digits: Int = 4): String { +internal fun format(value: Double, digits: Int = 4): String { val ten = 10.0 - val approxOrder = if(value == 0.0) 0 else ceil(log10(abs(value))).toInt() - val order = if( + val approxOrder = if (value == 0.0) 0 else ceil(log10(abs(value))).toInt() + val order = if ( ((value % ten) == 0.0) or (value == 1.0) or - ((1/value) % ten == 0.0)) approxOrder else approxOrder - 1 + ((1 / value) % ten == 0.0) + ) approxOrder else approxOrder - 1 val lead = value / ten.pow(order) - val leadDisplay = round(lead*ten.pow(digits)) / ten.pow(digits) - val orderDisplay = if(order == 0) "" else if(order > 0) "E+$order" else "E$order" + val leadDisplay = round(lead * ten.pow(digits)) / ten.pow(digits) + val orderDisplay = if (order == 0) "" else if (order > 0) "E+$order" else "E$order" val valueDisplay = "$leadDisplay$orderDisplay" - val res = if(value < 0.0) valueDisplay else " $valueDisplay" + val res = if (value < 0.0) valueDisplay else " $valueDisplay" val fLength = digits + 6 val endSpace = " ".repeat(fLength - res.length) return "$res$endSpace" } -internal inline fun DoubleTensor.toPrettyString(): String = buildString { +internal fun DoubleTensor.toPrettyString(): String = buildString { var offset = 0 val shape = this@toPrettyString.shape val linearStructure = this@toPrettyString.linearStructure @@ -72,32 +73,36 @@ internal inline fun DoubleTensor.toPrettyString(): String = buildString { append(initString) var charOffset = 3 for (vector in vectorSequence()) { - append(" ".repeat(charOffset)) + repeat(charOffset) { append(' ') } val index = linearStructure.index(offset) for (ind in index.reversed()) { if (ind != 0) { break } - append("[") + append('[') charOffset += 1 } val values = vector.as1D().toMutableList().map(::format) - append(values.joinToString(", ")) - append("]") + values.joinTo(this, separator = ", ") + + append(']') charOffset -= 1 - for ((ind, maxInd) in index.reversed().zip(shape.reversed()).drop(1)){ + + index.reversed().zip(shape.reversed()).drop(1).forEach { (ind, maxInd) -> if (ind != maxInd - 1) { - break + return@forEach } - append("]") - charOffset -=1 + append(']') + charOffset -= 1 } + offset += vectorSize if (this@toPrettyString.numElements == offset) { break } + append(",\n") } append("\n)") diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 1148c0aad..2282d7fcb 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -182,7 +182,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } -private inline fun DoubleLinearOpsTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10): Unit { +private fun DoubleLinearOpsTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10): Unit { val svd = tensor.svd() val tensorSVD = svd.first From 8a039326d40fe4e840bed09170607c457a89e5a3 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 19:47:05 +0100 Subject: [PATCH 266/393] Minor corrections --- kmath-core/api/kmath-core.api | 3 +-- .../kotlin/space/kscience/kmath/nd/StructureND.kt | 10 ++++------ .../tensors/core/algebras/TensorLinearStructure.kt | 5 ----- .../kscience/kmath/tensors/core/broadcastUtils.kt | 13 ++++++------- .../kmath/tensors/core/TestDoubleTensorAlgebra.kt | 1 - 5 files changed, 11 insertions(+), 21 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 687de9cc8..261aa1e24 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -792,7 +792,6 @@ public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath public fun getStrides ()[I public fun hashCode ()I public fun index (I)[I - public fun offset ([I)I } public final class space/kscience/kmath/nd/DefaultStrides$Companion { @@ -934,7 +933,7 @@ public abstract interface class space/kscience/kmath/nd/Strides { public abstract fun getStrides ()[I public abstract fun index (I)[I public fun indices ()Lkotlin/sequences/Sequence; - public abstract fun offset ([I)I + public fun offset ([I)I } public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/StructureND, space/kscience/kmath/structures/Buffer { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index 65c233012..a3331d71a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -189,7 +189,10 @@ public interface Strides { /** * Get linear index from multidimensional index */ - public fun offset(index: IntArray): Int + public fun offset(index: IntArray): Int = index.mapIndexed { i, value -> + if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${this.shape[i]})") + value * strides[i] + }.sum() /** * Get multidimensional from linear @@ -233,11 +236,6 @@ public class DefaultStrides private constructor(override val shape: IntArray) : }.toList().toIntArray() } - override fun offset(index: IntArray): Int = index.mapIndexed { i, value -> - if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${this.shape[i]})") - value * strides[i] - }.sum() - override fun index(offset: Int): IntArray { val res = IntArray(shape.size) var current = offset diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index 8e83dafd6..08aab5175 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -68,8 +68,6 @@ public class TensorLinearStructure(override val shape: IntArray) : Strides override val strides: IntArray get() = stridesFromShape(shape) - override fun offset(index: IntArray): Int = offsetFromIndex(index, shape, strides) - override fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) @@ -82,7 +80,4 @@ public class TensorLinearStructure(override val shape: IntArray) : Strides public val dim: Int get() = shape.size - override fun indices(): Sequence = (0 until linearSize).asSequence().map { - index(it) - } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt index 58d8654af..e883b7861 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt @@ -75,14 +75,13 @@ internal fun broadcastTensors(vararg tensors: DoubleTensor): List val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) val n = totalShape.reduce { acc, i -> acc * i } - val res = ArrayList(0) - for (tensor in tensors) { - val resTensor = DoubleTensor(totalShape, DoubleArray(n)) - multiIndexBroadCasting(tensor, resTensor, n) - res.add(resTensor) + return buildList { + for (tensor in tensors) { + val resTensor = DoubleTensor(totalShape, DoubleArray(n)) + multiIndexBroadCasting(tensor, resTensor, n) + add(resTensor) + } } - - return res } internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List { diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 34fe5d5f1..a0efa4573 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -170,7 +170,6 @@ internal class TestDoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) - val tensor4 = fromArray(intArrayOf(6, 1), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) assertTrue(tensor1 eq tensor1) assertTrue(tensor1 eq tensor2) From 74773686b432eac9e7d7804ffabf38eb1dbf1dca Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 19:49:43 +0100 Subject: [PATCH 267/393] toDoubleTensor and toIntTensor renaming --- .../space/kscience/kmath/tensors/core/BufferedTensor.kt | 4 ++-- .../space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 21030bbc7..4e286b489 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -77,5 +77,5 @@ internal val TensorStructure.tensor: IntTensor else -> this.toBufferedTensor().asTensor() } -public fun TensorStructure.toTypedTensor(): DoubleTensor = this.tensor -public fun TensorStructure.toTypedTensor(): IntTensor = this.tensor \ No newline at end of file +public fun TensorStructure.toDoubleTensor(): DoubleTensor = this.tensor +public fun TensorStructure.toIntTensor(): IntTensor = this.tensor \ No newline at end of file diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index eca54f68b..333a7bdec 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -67,8 +67,8 @@ internal class TestDoubleTensor { val bufferedTensorArray = ndArray.toBufferedTensor() // strides are flipped so data copied val tensorArray = bufferedTensorArray.asTensor() // data not contiguous so copied again - val tensorArrayPublic = ndArray.toTypedTensor() // public API, data copied twice - val sharedTensorArray = tensorArrayPublic.toTypedTensor() // no data copied by matching type + val tensorArrayPublic = ndArray.toDoubleTensor() // public API, data copied twice + val sharedTensorArray = tensorArrayPublic.toDoubleTensor() // no data copied by matching type assertTrue(tensorArray.mutableBuffer.array() contentEquals sharedTensorArray.mutableBuffer.array()) From 1b6bd67b903f761bf009a0677e422f637dd775d4 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 30 Apr 2021 21:11:01 +0100 Subject: [PATCH 268/393] No virtual mutable buffers --- kmath-core/api/kmath-core.api | 9 --------- .../space/kscience/kmath/nd/Structure2D.kt | 6 +++--- .../space/kscience/kmath/structures/Buffer.kt | 18 ------------------ 3 files changed, 3 insertions(+), 30 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 261aa1e24..865ad2f6d 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -1881,15 +1881,6 @@ public final class space/kscience/kmath/structures/MutableBuffer$Companion { public final fun short-1yRgbGw (ILkotlin/jvm/functions/Function1;)[S } -public final class space/kscience/kmath/structures/MutableBufferFromGenerator : space/kscience/kmath/structures/MutableBuffer { - public fun (ILkotlin/jvm/functions/Function1;)V - public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; - public fun get (I)Ljava/lang/Object; - public fun getSize ()I - public fun iterator ()Ljava/util/Iterator; - public fun set (ILjava/lang/Object;)V -} - public final class space/kscience/kmath/structures/MutableListBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/MutableListBuffer; public static fun constructor-impl (ILkotlin/jvm/functions/Function1;)Ljava/util/List; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index d987d8cf4..28ae07a3c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.VirtualBuffer -import space.kscience.kmath.structures.MutableBufferFromGenerator +import space.kscience.kmath.structures.MutableListBuffer import kotlin.jvm.JvmInline import kotlin.reflect.KClass @@ -81,13 +81,13 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { * The buffer of rows of this structure. It gets elements from the structure dynamically. */ override val rows: List> - get() = List(rowNum) { i -> MutableBuffer1DWrapper(MutableBufferFromGenerator(colNum) { j -> get(i, j) })} + get() = List(rowNum) { i -> MutableBuffer1DWrapper(MutableListBuffer(colNum) { j -> get(i, j) })} /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ override val columns: List> - get() = List(colNum) { j -> MutableBuffer1DWrapper(MutableBufferFromGenerator(rowNum) { i -> get(i, j) }) } + get() = List(colNum) { j -> MutableBuffer1DWrapper(MutableListBuffer(rowNum) { i -> get(i, j) }) } } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 19018ffb5..be5dfb359 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -292,24 +292,6 @@ public class VirtualBuffer(override val size: Int, private val generator: (In override operator fun iterator(): Iterator = (0 until size).asSequence().map(generator).iterator() } -public class MutableBufferFromGenerator(override val size: Int, private val generator: (Int) -> T) : MutableBuffer { - - private val bufferHolder: MutableListBuffer = (0 until size).map(generator).toMutableList().asMutableBuffer() - - override operator fun get(index: Int): T { - if (index < 0 || index >= size) throw IndexOutOfBoundsException("Expected index from 0 to ${size - 1}, but found $index") - return bufferHolder[index] - } - - override operator fun iterator(): Iterator = bufferHolder.iterator() - - override fun set(index: Int, value: T) { - bufferHolder[index] = value - } - - override fun copy(): MutableBuffer = bufferHolder.copy() -} - /** * Convert this buffer to read-only buffer. */ From b7cac3a015d235d81d02d3bb4b8834dda2b48b95 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sat, 1 May 2021 13:32:50 +0300 Subject: [PATCH 269/393] fix sequences + array casting --- .../kmath/tensors/core/BufferedTensor.kt | 38 ++++++++++++++++++- .../kscience/kmath/tensors/core/linUtils.kt | 4 +- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 4e286b489..867b4fb7a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -49,6 +49,7 @@ public class DoubleTensor internal constructor( internal fun BufferedTensor.asTensor(): IntTensor = IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) + internal fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) @@ -78,4 +79,39 @@ internal val TensorStructure.tensor: IntTensor } public fun TensorStructure.toDoubleTensor(): DoubleTensor = this.tensor -public fun TensorStructure.toIntTensor(): IntTensor = this.tensor \ No newline at end of file +public fun TensorStructure.toIntTensor(): IntTensor = this.tensor + +public fun Array.toDoubleTensor(): DoubleTensor { + val n = size + check(n > 0) { "An empty array cannot be casted to tensor" } + val m = first().size + check(m > 0) { "Inner arrays must have at least 1 argument" } + check(all { size == m }) { "Inner arrays must be the same size" } + + val shape = intArrayOf(n, m) + val buffer = this.flatMap { arr -> arr.map { it } }.toDoubleArray() + + return DoubleTensor(shape, buffer, 0) +} + + +public fun Array.toIntTensor(): IntTensor { + val n = size + check(n > 0) { "An empty array cannot be casted to tensor" } + val m = first().size + check(m > 0) { "Inner arrays must have at least 1 argument" } + check(all { size == m }) { "Inner arrays must be the same size" } + + val shape = intArrayOf(n, m) + val buffer = this.flatMap { arr -> arr.map { it } }.toIntArray() + + return IntTensor(shape, buffer, 0) +} + +public fun DoubleTensor.toDoubleArray(): DoubleArray { + return tensor.mutableBuffer.array().drop(bufferStart).take(numElements).toDoubleArray() +} + +public fun IntTensor.toIntArray(): IntArray { + return tensor.mutableBuffer.array().drop(bufferStart).take(numElements).toIntArray() +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt index a152b3a17..e54cc4d26 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt @@ -18,7 +18,7 @@ internal fun BufferedTensor.vectorSequence(): Sequence> val vectorOffset = shape[n - 1] val vectorShape = intArrayOf(shape.last()) for (offset in 0 until numElements step vectorOffset) { - val vector = BufferedTensor(vectorShape, mutableBuffer, offset) + val vector = BufferedTensor(vectorShape, mutableBuffer, bufferStart + offset) yield(vector) } } @@ -29,7 +29,7 @@ internal fun BufferedTensor.matrixSequence(): Sequence> val matrixOffset = shape[n - 1] * shape[n - 2] val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) for (offset in 0 until numElements step matrixOffset) { - val matrix = BufferedTensor(matrixShape, mutableBuffer, offset) + val matrix = BufferedTensor(matrixShape, mutableBuffer, bufferStart + offset) yield(matrix) } } From fe81dea243860ad063d5490d13225182ddbfaedc Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sat, 1 May 2021 14:22:05 +0300 Subject: [PATCH 270/393] stack --- .../core/algebras/DoubleTensorAlgebra.kt | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index f428b9d2e..c6fb301b5 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -382,7 +382,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return false } for (i in 0 until n) { - if (!eqFunction(tensor.mutableBuffer[tensor.bufferStart + i], other.tensor.mutableBuffer[other.tensor.bufferStart + i])) { + if (!eqFunction( + tensor.mutableBuffer[tensor.bufferStart + i], + other.tensor.mutableBuffer[other.tensor.bufferStart + i] + ) + ) { return false } } @@ -395,4 +399,20 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun TensorStructure.randNormalLike(seed: Long = 0): DoubleTensor = DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) + // stack tensors by axis 0 + public fun stack(tensors: List): DoubleTensor { + val shape = tensors.firstOrNull()?.shape + check(shape != null) { "Collection must have at least 1 element" } + check(tensors.all { it.shape contentEquals shape }) {"Stacking tensors must have same shapes"} + val resShape = intArrayOf(tensors.size) + shape + val resBuffer = tensors.flatMap { + it.tensor.mutableBuffer.array().drop(it.bufferStart).take(it.numElements) + }.toDoubleArray() + return DoubleTensor(resShape, resBuffer, 0) + } + + // build tensor from this rows by given indices + public fun TensorStructure.rowsByIndices(indices: IntArray): DoubleTensor { + return stack(indices.map { this[it] }) + } } From 83c7ec8c6b7cf52cd7a890a4e1551140327ec6dd Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 1 May 2021 00:13:32 +0700 Subject: [PATCH 271/393] Deprecate AlgebraElements.kt --- kmath-core/api/kmath-core.api | 7 ------- .../kscience/kmath/operations/AlgebraElements.kt | 14 +++++++++++++- .../kmath/operations/OptionalOperations.kt | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 6b300123c..a73e4ed54 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -991,14 +991,7 @@ public abstract interface class space/kscience/kmath/operations/Algebra { public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } -public abstract interface class space/kscience/kmath/operations/AlgebraElement { - public abstract fun getContext ()Lspace/kscience/kmath/operations/Algebra; -} - public final class space/kscience/kmath/operations/AlgebraElementsKt { - public static final fun div (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement; - public static final fun plus (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement; - public static final fun times (Lspace/kscience/kmath/operations/AlgebraElement;Lspace/kscience/kmath/operations/AlgebraElement;)Lspace/kscience/kmath/operations/AlgebraElement; } public final class space/kscience/kmath/operations/AlgebraExtensionsKt { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt index d7c87f213..cc058d3fc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/AlgebraElements.kt @@ -13,6 +13,8 @@ import space.kscience.kmath.misc.UnstableKMathAPI * @param C the type of mathematical context for this element. * @param T the type wrapped by this wrapper. */ +@UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public interface AlgebraElement> { /** * The context this element belongs to. @@ -45,6 +47,7 @@ public interface AlgebraElement> { * @return the difference. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public operator fun , S : NumbersAddOperations> T.minus(b: T): T = context.add(this, context.run { -b }) @@ -55,6 +58,8 @@ public operator fun , S : NumbersAddOperations> T.mi * @param b the addend. * @return the sum. */ +@UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public operator fun , S : Ring> T.plus(b: T): T = context.add(this, b) @@ -71,6 +76,8 @@ public operator fun , S : Ring> T.plus(b: T): T = * @param b the multiplier. * @return the product. */ +@UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public operator fun , R : Ring> T.times(b: T): T = context.multiply(this, b) @@ -81,6 +88,8 @@ public operator fun , R : Ring> T.times(b: T): T = * @param b the divisor. * @return the quotient. */ +@UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public operator fun , F : Field> T.div(b: T): T = context.divide(this, b) @@ -93,6 +102,7 @@ public operator fun , F : Field> T.div(b: T): T = * @param S the type of space. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public interface GroupElement, S : Group> : AlgebraElement /** @@ -103,6 +113,7 @@ public interface GroupElement, S : Group> : AlgebraEle * @param R the type of ring. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public interface RingElement, R : Ring> : GroupElement /** @@ -113,4 +124,5 @@ public interface RingElement, R : Ring> : GroupElement< * @param F the type of field. */ @UnstableKMathAPI -public interface FieldElement, F : Field> : RingElement \ No newline at end of file +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") +public interface FieldElement, F : Field> : RingElement diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt index 8e3e6c777..979e65396 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt @@ -80,36 +80,42 @@ public interface TrigonometricOperations : Algebra { * Computes the sine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> sin(arg: T): T = arg.context.sin(arg) /** * Computes the cosine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> cos(arg: T): T = arg.context.cos(arg) /** * Computes the tangent of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> tan(arg: T): T = arg.context.tan(arg) /** * Computes the inverse sine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> asin(arg: T): T = arg.context.asin(arg) /** * Computes the inverse cosine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> acos(arg: T): T = arg.context.acos(arg) /** * Computes the inverse tangent of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> atan(arg: T): T = arg.context.atan(arg) /** @@ -154,18 +160,21 @@ public interface PowerOperations : Algebra { * @return the base raised to the power. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public infix fun >> T.pow(power: Double): T = context.power(this, power) /** * Computes the square root of the value [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> sqrt(arg: T): T = arg pow 0.5 /** * Computes the square of the value [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> sqr(arg: T): T = arg pow 2.0 /** @@ -261,12 +270,14 @@ public interface ExponentialOperations : Algebra { * The identifier of exponential function. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> exp(arg: T): T = arg.context.exp(arg) /** * The identifier of natural logarithm. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> ln(arg: T): T = arg.context.ln(arg) @@ -280,30 +291,35 @@ public fun >> sinh(arg: T): T * Computes the hyperbolic cosine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> cosh(arg: T): T = arg.context.cosh(arg) /** * Computes the hyperbolic tangent of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> tanh(arg: T): T = arg.context.tanh(arg) /** * Computes the inverse hyperbolic sine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> asinh(arg: T): T = arg.context.asinh(arg) /** * Computes the inverse hyperbolic cosine of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> acosh(arg: T): T = arg.context.acosh(arg) /** * Computes the inverse hyperbolic tangent of [arg]. */ @UnstableKMathAPI +@Deprecated("AlgebraElements are considered odd and will be removed in future releases.") public fun >> atanh(arg: T): T = arg.context.atanh(arg) /** From bfba653904793b74be89ea9f46461ad8c20a2b8e Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sat, 1 May 2021 17:47:12 +0300 Subject: [PATCH 272/393] refactor --- .../kscience/kmath/tensors/OLSWithSVD.kt | 6 ++--- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 8 ++++--- .../core/algebras/DoubleTensorAlgebra.kt | 18 +++++++------- .../kmath/tensors/core/broadcastUtils.kt | 24 +++++++++---------- .../kscience/kmath/tensors/core/utils.kt | 3 +-- .../core/TestDoubleLinearOpsAlgebra.kt | 6 ++--- 6 files changed, 32 insertions(+), 33 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 0408bba63..095905f05 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -21,7 +21,7 @@ fun main() { // work in context with linear operations DoubleLinearOpsTensorAlgebra.invoke { // take coefficient vector from normal distribution - val alpha = randNormal( + val alpha = randomNormal( intArrayOf(5), randSeed ) + fromArray( @@ -32,14 +32,14 @@ fun main() { println("Real alpha:\n$alpha") // also take sample of size 20 from normal distribution for x - val x = randNormal( + val x = randomNormal( intArrayOf(20, 5), randSeed ) // calculate y and add gaussian noise (N(0, 0.05)) val y = x dot alpha - y += y.randNormalLike(randSeed) * 0.05 + y += y.randomNormalLike(randSeed) * 0.05 // now restore the coefficient vector with OSL estimator with SVD val (u, singValues, v) = x.svd() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 700fafbeb..dd5ad5a61 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -31,7 +31,7 @@ public object DoubleLinearOpsTensorAlgebra : public fun TensorStructure.luFactor(epsilon: Double): Pair = computeLU(tensor, epsilon) - ?: throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon") + ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") public fun TensorStructure.luFactor(): Pair = luFactor(1e-9) @@ -47,8 +47,10 @@ public object DoubleLinearOpsTensorAlgebra : val n = luTensor.shape.last() val pTensor = luTensor.zeroesLike() - for ((p, pivot) in pTensor.matrixSequence().zip(pivotsTensor.tensor.vectorSequence())) - pivInit(p.as2D(), pivot.as1D(), n) + pTensor + .matrixSequence() + .zip(pivotsTensor.tensor.vectorSequence()) + .forEach { (p, pivot) -> pivInit(p.as2D(), pivot.as1D(), n) } val lTensor = luTensor.zeroesLike() val uTensor = luTensor.zeroesLike() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index c6fb301b5..d3e8bf175 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -284,7 +284,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { val m1 = newThis.shape[newThis.shape.size - 1] val m2 = newOther.shape[newOther.shape.size - 2] val n = newOther.shape[newOther.shape.size - 1] - if (m1 != m2) { + check (m1 == m2) { throw RuntimeException("Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)") } @@ -315,11 +315,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { val d1 = minusIndexFrom(n + 1, dim1) val d2 = minusIndexFrom(n + 1, dim2) - if (d1 == d2) { - throw RuntimeException("Diagonal dimensions cannot be identical $d1, $d2") + check(d1 != d2) { + "Diagonal dimensions cannot be identical $d1, $d2" } - if (d1 > n || d2 > n) { - throw RuntimeException("Dimension out of range") + check(d1 <= n && d2 <= n) { + "Dimension out of range" } var lessDim = d1 @@ -366,8 +366,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { ) } - public fun TensorStructure.eq(other: TensorStructure, delta: Double): Boolean { - return tensor.eq(other) { x, y -> abs(x - y) < delta } + public fun TensorStructure.eq(other: TensorStructure, epsilon: Double): Boolean { + return tensor.eq(other) { x, y -> abs(x - y) < epsilon } } public infix fun TensorStructure.eq(other: TensorStructure): Boolean = tensor.eq(other, 1e-5) @@ -393,10 +393,10 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return true } - public fun randNormal(shape: IntArray, seed: Long = 0): DoubleTensor = + public fun randomNormal(shape: IntArray, seed: Long = 0): DoubleTensor = DoubleTensor(shape, getRandomNormals(shape.reduce(Int::times), seed)) - public fun TensorStructure.randNormalLike(seed: Long = 0): DoubleTensor = + public fun TensorStructure.randomNormalLike(seed: Long = 0): DoubleTensor = DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) // stack tensors by axis 0 diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt index e883b7861..dfac054b5 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt @@ -42,8 +42,8 @@ internal fun broadcastShapes(vararg shapes: IntArray): IntArray { for (i in shape.indices) { val curDim = shape[i] val offset = totalDim - shape.size - if (curDim != 1 && totalShape[i + offset] != curDim) { - throw RuntimeException("Shapes are not compatible and cannot be broadcast") + check(curDim == 1 || totalShape[i + offset] == curDim) { + "Shapes are not compatible and cannot be broadcast" } } } @@ -52,8 +52,8 @@ internal fun broadcastShapes(vararg shapes: IntArray): IntArray { } internal fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor { - if (tensor.shape.size > newShape.size) { - throw RuntimeException("Tensor is not compatible with the new shape") + require(tensor.shape.size <= newShape.size) { + "Tensor is not compatible with the new shape" } val n = newShape.reduce { acc, i -> acc * i } @@ -62,8 +62,8 @@ internal fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor for (i in tensor.shape.indices) { val curDim = tensor.shape[i] val offset = newShape.size - tensor.shape.size - if (curDim != 1 && newShape[i + offset] != curDim) { - throw RuntimeException("Tensor is not compatible with the new shape and cannot be broadcast") + check(curDim == 1 || newShape[i + offset] == curDim) { + "Tensor is not compatible with the new shape and cannot be broadcast" } } @@ -75,19 +75,17 @@ internal fun broadcastTensors(vararg tensors: DoubleTensor): List val totalShape = broadcastShapes(*(tensors.map { it.shape }).toTypedArray()) val n = totalShape.reduce { acc, i -> acc * i } - return buildList { - for (tensor in tensors) { - val resTensor = DoubleTensor(totalShape, DoubleArray(n)) - multiIndexBroadCasting(tensor, resTensor, n) - add(resTensor) - } + return tensors.map { tensor -> + val resTensor = DoubleTensor(totalShape, DoubleArray(n)) + multiIndexBroadCasting(tensor, resTensor, n) + resTensor } } internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List { val onlyTwoDims = tensors.asSequence().onEach { require(it.shape.size >= 2) { - throw RuntimeException("Tensors must have at least 2 dimensions") + "Tensors must have at least 2 dimensions" } }.any { it.shape.size != 2 } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 58d280307..88b9c6c5c 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -69,8 +69,7 @@ internal fun DoubleTensor.toPrettyString(): String = buildString { val shape = this@toPrettyString.shape val linearStructure = this@toPrettyString.linearStructure val vectorSize = shape.last() - val initString = "DoubleTensor(\n" - append(initString) + append("DoubleTensor(\n") var charOffset = 3 for (vector in vectorSequence()) { repeat(charOffset) { append(' ') } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 2282d7fcb..6689e893a 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -135,7 +135,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testCholesky() = DoubleLinearOpsTensorAlgebra.invoke { - val tensor = randNormal(intArrayOf(2, 5, 5), 0) + val tensor = randomNormal(intArrayOf(2, 5, 5), 0) val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) ) @@ -163,7 +163,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra.invoke { - val tensor = randNormal(intArrayOf(2, 5, 3), 0) + val tensor = randomNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) assertTrue(tensor.eq(tensorSVD)) @@ -171,7 +171,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra.invoke { - val tensor = randNormal(shape = intArrayOf(2, 3, 3), 0) + val tensor = randomNormal(shape = intArrayOf(2, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) From ac6608b5b45ed7b59667216ec62b73380f60ef97 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Sat, 1 May 2021 20:45:23 +0300 Subject: [PATCH 273/393] refactor --- .../tensors/LinearSystemSolvingWithLUP.kt | 2 +- .../kscience/kmath/tensors/OLSWithSVD.kt | 2 +- kmath-tensors/build.gradle.kts | 3 ++ .../kmath/tensors/core/BufferedTensor.kt | 8 +++- .../kscience/kmath/tensors/core/checks.kt | 23 ++++------ .../kscience/kmath/tensors/core/linUtils.kt | 12 ----- .../kscience/kmath/tensors/core/utils.kt | 45 +++++++++++-------- 7 files changed, 47 insertions(+), 48 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index a84224bcf..bd8233ccc 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -14,7 +14,7 @@ import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra fun main () { // work in context with linear operations - DoubleLinearOpsTensorAlgebra.invoke { + DoubleLinearOpsTensorAlgebra { // set true value of x val trueX = fromArray( diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 095905f05..435af35f6 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -19,7 +19,7 @@ fun main() { val randSeed = 100500L // work in context with linear operations - DoubleLinearOpsTensorAlgebra.invoke { + DoubleLinearOpsTensorAlgebra { // take coefficient vector from normal distribution val alpha = randomNormal( intArrayOf(5), diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts index af5116022..b7f24dc6a 100644 --- a/kmath-tensors/build.gradle.kts +++ b/kmath-tensors/build.gradle.kts @@ -3,6 +3,9 @@ plugins { } kotlin.sourceSets { + all { + languageSettings.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") + } commonMain { dependencies { api(project(":kmath-core")) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 867b4fb7a..9541a97f9 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -109,9 +109,13 @@ public fun Array.toIntTensor(): IntTensor { } public fun DoubleTensor.toDoubleArray(): DoubleArray { - return tensor.mutableBuffer.array().drop(bufferStart).take(numElements).toDoubleArray() + return DoubleArray(numElements) { i -> + mutableBuffer[bufferStart + i] + } } public fun IntTensor.toIntArray(): IntArray { - return tensor.mutableBuffer.array().drop(bufferStart).take(numElements).toIntArray() + return IntArray(numElements) { i -> + mutableBuffer[bufferStart + i] + } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index fd98be8b2..b1c12ccde 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -5,38 +5,35 @@ import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra -internal fun checkEmptyShape(shape: IntArray): Unit = +internal fun checkEmptyShape(shape: IntArray) = check(shape.isNotEmpty()) { "Illegal empty shape provided" } -internal fun checkEmptyDoubleBuffer(buffer: DoubleArray): Unit = +internal fun checkEmptyDoubleBuffer(buffer: DoubleArray) = check(buffer.isNotEmpty()) { "Illegal empty buffer provided" } -internal fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray): Unit = +internal fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray) = check(buffer.size == shape.reduce(Int::times)) { "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" } - -internal fun checkShapesCompatible(a: TensorStructure, b: TensorStructure): Unit = +internal fun checkShapesCompatible(a: TensorStructure, b: TensorStructure) = check(a.shape contentEquals b.shape) { "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " } - -internal fun checkTranspose(dim: Int, i: Int, j: Int): Unit = +internal fun checkTranspose(dim: Int, i: Int, j: Int) = check((i < dim) and (j < dim)) { "Cannot transpose $i to $j for a tensor of dim $dim" } -internal fun checkView(a: TensorStructure, shape: IntArray): Unit = +internal fun checkView(a: TensorStructure, shape: IntArray) = check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) - -internal fun checkSquareMatrix(shape: IntArray): Unit { +internal fun checkSquareMatrix(shape: IntArray) { val n = shape.size check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n instead" @@ -48,14 +45,12 @@ internal fun checkSquareMatrix(shape: IntArray): Unit { internal fun DoubleTensorAlgebra.checkSymmetric( tensor: TensorStructure, epsilon: Double = 1e-6 -): Unit = +) = check(tensor.eq(tensor.transpose(), epsilon)) { "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } -internal fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite( - tensor: DoubleTensor, epsilon: Double = 1e-6 -): Unit { +internal fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { checkSymmetric(tensor, epsilon) for (mat in tensor.matrixSequence()) check(mat.asTensor().detLU().value() > 0.0) { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt index e54cc4d26..ba8b823c9 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt @@ -34,18 +34,6 @@ internal fun BufferedTensor.matrixSequence(): Sequence> } } -internal inline fun BufferedTensor.forEachVector(vectorAction: (BufferedTensor) -> Unit) { - for (vector in vectorSequence()) { - vectorAction(vector) - } -} - -internal inline fun BufferedTensor.forEachMatrix(matrixAction: (BufferedTensor) -> Unit) { - for (matrix in matrixSequence()) { - matrixAction(matrix) - } -} - internal fun dotHelper( a: MutableStructure2D, b: MutableStructure2D, diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt index 88b9c6c5c..0211342bb 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt @@ -14,7 +14,6 @@ internal fun Buffer.array(): IntArray = when (this) { else -> this.toIntArray() } - /** * Returns a reference to [DoubleArray] containing all of the elements of this [Buffer] or copy the data. */ @@ -31,7 +30,7 @@ internal fun getRandomNormals(n: Int, seed: Long): DoubleArray { internal fun getRandomUnitVector(n: Int, seed: Long): DoubleArray { val unnorm = getRandomNormals(n, seed) - val norm = sqrt(unnorm.map { it * it }.sum()) + val norm = sqrt(unnorm.sumOf { it * it }) return unnorm.map { it / norm }.toDoubleArray() } @@ -45,23 +44,33 @@ internal fun minusIndexFrom(n: Int, i: Int): Int = if (i >= 0) i else { internal fun BufferedTensor.minusIndex(i: Int): Int = minusIndexFrom(this.dimension, i) -internal fun format(value: Double, digits: Int = 4): String { - val ten = 10.0 - val approxOrder = if (value == 0.0) 0 else ceil(log10(abs(value))).toInt() - val order = if ( - ((value % ten) == 0.0) or - (value == 1.0) or - ((1 / value) % ten == 0.0) - ) approxOrder else approxOrder - 1 - val lead = value / ten.pow(order) - val leadDisplay = round(lead * ten.pow(digits)) / ten.pow(digits) - val orderDisplay = if (order == 0) "" else if (order > 0) "E+$order" else "E$order" - val valueDisplay = "$leadDisplay$orderDisplay" - val res = if (value < 0.0) valueDisplay else " $valueDisplay" - +internal fun format(value: Double, digits: Int = 4): String = buildString { + val res = buildString { + val ten = 10.0 + val approxOrder = if (value == 0.0) 0 else ceil(log10(abs(value))).toInt() + val order = if ( + ((value % ten) == 0.0) || + (value == 1.0) || + ((1 / value) % ten == 0.0) + ) approxOrder else approxOrder - 1 + val lead = value / ten.pow(order) + if (value >= 0.0) append(' ') + append(round(lead * ten.pow(digits)) / ten.pow(digits)) + when { + order == 0 -> Unit + order > 0 -> { + append("e+") + append(order) + } + else -> { + append('e') + append(order) + } + } + } val fLength = digits + 6 - val endSpace = " ".repeat(fLength - res.length) - return "$res$endSpace" + append(res) + repeat(fLength - res.length) { append(' ') } } internal fun DoubleTensor.toPrettyString(): String = buildString { From 48d86fac5620b5e663a5dc62618f4f2869e86521 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sat, 1 May 2021 19:55:48 +0100 Subject: [PATCH 274/393] invoke refactor --- .../core/algebras/TensorLinearStructure.kt | 6 ----- .../kscience/kmath/tensors/core/linUtils.kt | 2 +- .../kmath/tensors/core/TestBroadcasting.kt | 10 ++++---- .../core/TestDoubleAnalyticTensorAlgebra.kt | 2 +- .../core/TestDoubleLinearOpsAlgebra.kt | 24 +++++++++---------- .../kmath/tensors/core/TestDoubleTensor.kt | 6 ++--- .../tensors/core/TestDoubleTensorAlgebra.kt | 18 +++++++------- 7 files changed, 31 insertions(+), 37 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index 08aab5175..5fbc7390f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -9,12 +9,6 @@ import space.kscience.kmath.nd.Strides import kotlin.math.max -internal fun offsetFromIndex(index: IntArray, shape: IntArray, strides: IntArray): Int = - index.mapIndexed { i, value -> - if (value < 0 || value >= shape[i]) throw IndexOutOfBoundsException("Index $value out of shape bounds: (0,${shape[i]})") - value * strides[i] - }.sum() - internal fun stridesFromShape(shape: IntArray): IntArray { val nDim = shape.size val res = IntArray(nDim) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt index ba8b823c9..8adbfad39 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt @@ -241,7 +241,7 @@ internal fun DoubleLinearOpsTensorAlgebra.qrHelper( } } } - r[j, j] = DoubleAnalyticTensorAlgebra.invoke { (v dot v).sqrt().value() } + r[j, j] = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 1070a1115..1564b85c9 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -9,7 +9,7 @@ import kotlin.test.assertTrue internal class TestBroadcasting { @Test - fun broadcastShapes() = DoubleTensorAlgebra.invoke { + fun broadcastShapes() = DoubleTensorAlgebra { assertTrue( broadcastShapes( intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) @@ -24,7 +24,7 @@ internal class TestBroadcasting { } @Test - fun broadcastTo() = DoubleTensorAlgebra.invoke { + fun broadcastTo() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) @@ -34,7 +34,7 @@ internal class TestBroadcasting { } @Test - fun broadcastTensors() = DoubleTensorAlgebra.invoke { + fun broadcastTensors() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -51,7 +51,7 @@ internal class TestBroadcasting { } @Test - fun broadcastOuterTensors() = DoubleTensorAlgebra.invoke { + fun broadcastOuterTensors() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -68,7 +68,7 @@ internal class TestBroadcasting { } @Test - fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra.invoke { + fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) {0.0}) val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) {0.0}) val tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0)) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 66959a0de..835b8a08a 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -27,7 +27,7 @@ internal class TestDoubleAnalyticTensorAlgebra { } @Test - fun testExp() = DoubleAnalyticTensorAlgebra.invoke { + fun testExp() = DoubleAnalyticTensorAlgebra { tensor.exp().let { assertTrue { shape contentEquals it.shape } assertTrue { buffer.fmap(::exp).epsEqual(it.mutableBuffer.array())} diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 6689e893a..65070af7f 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -10,7 +10,7 @@ import kotlin.test.assertTrue internal class TestDoubleLinearOpsTensorAlgebra { @Test - fun testDetLU() = DoubleLinearOpsTensorAlgebra.invoke { + fun testDetLU() = DoubleLinearOpsTensorAlgebra { val tensor = fromArray( intArrayOf(2, 2, 2), doubleArrayOf( @@ -35,7 +35,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testDet() = DoubleLinearOpsTensorAlgebra.invoke { + fun testDet() = DoubleLinearOpsTensorAlgebra { val expectedValue = 0.019827417 val m = fromArray( intArrayOf(3, 3), doubleArrayOf( @@ -49,7 +49,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testDetSingle() = DoubleLinearOpsTensorAlgebra.invoke { + fun testDetSingle() = DoubleLinearOpsTensorAlgebra { val expectedValue = 48.151623 val m = fromArray( intArrayOf(1, 1), doubleArrayOf( @@ -61,7 +61,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testInvLU() = DoubleLinearOpsTensorAlgebra.invoke { + fun testInvLU() = DoubleLinearOpsTensorAlgebra { val tensor = fromArray( intArrayOf(2, 2, 2), doubleArrayOf( @@ -86,14 +86,14 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testScalarProduct() = DoubleLinearOpsTensorAlgebra.invoke { + fun testScalarProduct() = DoubleLinearOpsTensorAlgebra { val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) assertEquals(a.dot(b).value(), 59.92) } @Test - fun testQR() = DoubleLinearOpsTensorAlgebra.invoke { + fun testQR() = DoubleLinearOpsTensorAlgebra { val shape = intArrayOf(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, @@ -114,7 +114,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testLU() = DoubleLinearOpsTensorAlgebra.invoke { + fun testLU() = DoubleLinearOpsTensorAlgebra { val shape = intArrayOf(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, @@ -134,7 +134,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testCholesky() = DoubleLinearOpsTensorAlgebra.invoke { + fun testCholesky() = DoubleLinearOpsTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 5), 0) val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) @@ -145,7 +145,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testSVD1D() = DoubleLinearOpsTensorAlgebra.invoke { + fun testSVD1D() = DoubleLinearOpsTensorAlgebra { val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = svd1d(tensor2) @@ -156,13 +156,13 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testSVD() = DoubleLinearOpsTensorAlgebra.invoke{ + fun testSVD() = DoubleLinearOpsTensorAlgebra{ testSVDFor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } @Test - fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra.invoke { + fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) @@ -170,7 +170,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra.invoke { + fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { val tensor = randomNormal(shape = intArrayOf(2, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 333a7bdec..ed5f8e780 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -15,14 +15,14 @@ import kotlin.test.assertTrue internal class TestDoubleTensor { @Test - fun valueTest() = DoubleTensorAlgebra.invoke { + fun valueTest() = DoubleTensorAlgebra { val value = 12.5 val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @Test - fun stridesTest() = DoubleTensorAlgebra.invoke { + fun stridesTest() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) assertEquals(tensor[intArrayOf(0, 1)], 5.8) assertTrue( @@ -31,7 +31,7 @@ internal class TestDoubleTensor { } @Test - fun getTest() = DoubleTensorAlgebra.invoke { + fun getTest() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) val matrix = tensor[0].as2D() assertEquals(matrix[0, 1], 5.8) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index a0efa4573..df2d21b96 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -10,21 +10,21 @@ import kotlin.test.assertTrue internal class TestDoubleTensorAlgebra { @Test - fun doublePlus() = DoubleTensorAlgebra.invoke { + fun doublePlus() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(11.0, 12.0)) } @Test - fun doubleDiv() = DoubleTensorAlgebra.invoke { + fun doubleDiv() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0)) val res = 2.0/tensor assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 0.5)) } @Test - fun divDouble() = DoubleTensorAlgebra.invoke { + fun divDouble() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0)) val res = tensor / 2.5 assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(4.0, 2.0)) @@ -40,7 +40,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun transpose3x2() = DoubleTensorAlgebra.invoke { + fun transpose3x2() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) @@ -49,7 +49,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun transpose1x2x3() = DoubleTensorAlgebra.invoke { + fun transpose1x2x3() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transpose(0, 1) val res02 = tensor.transpose(-3, 2) @@ -65,7 +65,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun linearStructure() = DoubleTensorAlgebra.invoke { + fun linearStructure() = DoubleTensorAlgebra { val shape = intArrayOf(3) val tensorA = full(value = -4.5, shape = shape) val tensorB = full(value = 10.9, shape = shape) @@ -97,7 +97,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun dot() = DoubleTensorAlgebra.invoke { + fun dot() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor11 = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) @@ -133,7 +133,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun diagonalEmbedding() = DoubleTensorAlgebra.invoke { + fun diagonalEmbedding() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = zeros(intArrayOf(2, 3, 4, 5)) @@ -166,7 +166,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun testEq() = DoubleTensorAlgebra.invoke { + fun testEq() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0)) From 1fe1a74b48c6670aeaf0adfe217a5407795b71b8 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 1 May 2021 22:40:53 +0300 Subject: [PATCH 275/393] Create LICENSE.txt --- LICENSE.txt | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From c8fb770ffddb6428790a762e32513414503a2b32 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 1 May 2021 22:44:43 +0300 Subject: [PATCH 276/393] Rename LICENSE.txt to LICENSE --- LICENSE.txt => LICENSE | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename LICENSE.txt => LICENSE (100%) diff --git a/LICENSE.txt b/LICENSE similarity index 100% rename from LICENSE.txt rename to LICENSE From 5aaba0dae443605b3dedb4bc4ee7733922b8e41f Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Sun, 2 May 2021 16:19:05 +0100 Subject: [PATCH 277/393] TensorStructure to Tensor --- .../tensors/api/AnalyticTensorAlgebra.kt | 36 ++++----- .../tensors/api/LinearOpsTensorAlgebra.kt | 16 ++-- .../api/{TensorStructure.kt => Tensor.kt} | 2 +- .../kmath/tensors/api/TensorAlgebra.kt | 52 ++++++------ .../api/TensorPartialDivisionAlgebra.kt | 12 +-- .../kmath/tensors/core/BufferedTensor.kt | 16 ++-- .../algebras/BroadcastDoubleTensorAlgebra.kt | 18 ++--- .../algebras/DoubleAnalyticTensorAlgebra.kt | 36 ++++----- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 36 ++++----- .../core/algebras/DoubleTensorAlgebra.kt | 80 +++++++++---------- .../kscience/kmath/tensors/core/checks.kt | 8 +- 11 files changed, 156 insertions(+), 156 deletions(-) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/{TensorStructure.kt => Tensor.kt} (60%) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 5c92c56c4..cd13e0752 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.api /** - * Element-wise analytic operations on [TensorStructure]. + * Element-wise analytic operations on [Tensor]. * * @param T the type of items closed under analytic functions in the tensors. */ @@ -14,54 +14,54 @@ public interface AnalyticTensorAlgebra : TensorPartialDivisionAlgebra { //For information: https://pytorch.org/docs/stable/generated/torch.exp.html - public fun TensorStructure.exp(): TensorStructure + public fun Tensor.exp(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.log.html - public fun TensorStructure.log(): TensorStructure + public fun Tensor.log(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.sqrt.html - public fun TensorStructure.sqrt(): TensorStructure + public fun Tensor.sqrt(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.acos.html#torch.cos - public fun TensorStructure.cos(): TensorStructure + public fun Tensor.cos(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.acos.html#torch.acos - public fun TensorStructure.acos(): TensorStructure + public fun Tensor.acos(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.cosh - public fun TensorStructure.cosh(): TensorStructure + public fun Tensor.cosh(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.acosh.html#torch.acosh - public fun TensorStructure.acosh(): TensorStructure + public fun Tensor.acosh(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sin - public fun TensorStructure.sin(): TensorStructure + public fun Tensor.sin(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asin - public fun TensorStructure.asin(): TensorStructure + public fun Tensor.asin(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.sinh - public fun TensorStructure.sinh(): TensorStructure + public fun Tensor.sinh(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.asin.html#torch.asinh - public fun TensorStructure.asinh(): TensorStructure + public fun Tensor.asinh(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.atan.html#torch.tan - public fun TensorStructure.tan(): TensorStructure + public fun Tensor.tan(): Tensor //https://pytorch.org/docs/stable/generated/torch.atan.html#torch.atan - public fun TensorStructure.atan(): TensorStructure + public fun Tensor.atan(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.tanh - public fun TensorStructure.tanh(): TensorStructure + public fun Tensor.tanh(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.atanh.html#torch.atanh - public fun TensorStructure.atanh(): TensorStructure + public fun Tensor.atanh(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.ceil.html#torch.ceil - public fun TensorStructure.ceil(): TensorStructure + public fun Tensor.ceil(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.floor.html#torch.floor - public fun TensorStructure.floor(): TensorStructure + public fun Tensor.floor(): Tensor } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index bcbb52a1b..527e5d386 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.api /** - * Common linear algebra operations. Operates on [TensorStructure]. + * Common linear algebra operations. Operates on [Tensor]. * * @param T the type of items closed under division in the tensors. */ @@ -19,7 +19,7 @@ public interface LinearOpsTensorAlgebra : * * @return the determinant. */ - public fun TensorStructure.det(): TensorStructure + public fun Tensor.det(): Tensor /** * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input. @@ -29,7 +29,7 @@ public interface LinearOpsTensorAlgebra : * * @return the multiplicative inverse of a matrix. */ - public fun TensorStructure.inv(): TensorStructure + public fun Tensor.inv(): Tensor /** * Cholesky decomposition. @@ -44,7 +44,7 @@ public interface LinearOpsTensorAlgebra : * * @return the batch of L matrices. */ - public fun TensorStructure.cholesky(): TensorStructure + public fun Tensor.cholesky(): Tensor /** * QR decomposition. @@ -57,7 +57,7 @@ public interface LinearOpsTensorAlgebra : * * @return pair of Q and R tensors. */ - public fun TensorStructure.qr(): Pair, TensorStructure> + public fun Tensor.qr(): Pair, Tensor> /** * LUP decomposition @@ -70,7 +70,7 @@ public interface LinearOpsTensorAlgebra : * * * @return triple of P, L and U tensors */ - public fun TensorStructure.lu(): Triple, TensorStructure, TensorStructure> + public fun Tensor.lu(): Triple, Tensor, Tensor> /** * Singular Value Decomposition. @@ -83,7 +83,7 @@ public interface LinearOpsTensorAlgebra : * * @return the determinant. */ - public fun TensorStructure.svd(): Triple, TensorStructure, TensorStructure> + public fun Tensor.svd(): Triple, Tensor, Tensor> /** * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, @@ -92,6 +92,6 @@ public interface LinearOpsTensorAlgebra : * * @return a pair (eigenvalues, eigenvectors) */ - public fun TensorStructure.symEig(): Pair, TensorStructure> + public fun Tensor.symEig(): Pair, Tensor> } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt similarity index 60% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorStructure.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt index edecd6383..179787684 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt @@ -2,4 +2,4 @@ package space.kscience.kmath.tensors.api import space.kscience.kmath.nd.MutableStructureND -public typealias TensorStructure = MutableStructureND +public typealias Tensor = MutableStructureND diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 96d6985d8..b9c707c0b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -8,19 +8,19 @@ package space.kscience.kmath.tensors.api import space.kscience.kmath.operations.Algebra /** - * Algebra over a ring on [TensorStructure]. + * Algebra over a ring on [Tensor]. * For more information: https://proofwiki.org/wiki/Definition:Algebra_over_Ring * * @param T the type of items in the tensors. */ -public interface TensorAlgebra: Algebra> { +public interface TensorAlgebra: Algebra> { /** * Returns a single tensor value of unit dimension. The tensor shape must be equal to [1]. * * @return the value of a scalar tensor. */ - public fun TensorStructure.value(): T + public fun Tensor.value(): T /** * Each element of the tensor [other] is added to this value. @@ -29,7 +29,7 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be added. * @return the sum of this value and tensor [other]. */ - public operator fun T.plus(other: TensorStructure): TensorStructure + public operator fun T.plus(other: Tensor): Tensor /** * Adds the scalar [value] to each element of this tensor and returns a new resulting tensor. @@ -37,7 +37,7 @@ public interface TensorAlgebra: Algebra> { * @param value the number to be added to each element of this tensor. * @return the sum of this tensor and [value]. */ - public operator fun TensorStructure.plus(value: T): TensorStructure + public operator fun Tensor.plus(value: T): Tensor /** * Each element of the tensor [other] is added to each element of this tensor. @@ -46,21 +46,21 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be added. * @return the sum of this tensor and [other]. */ - public operator fun TensorStructure.plus(other: TensorStructure): TensorStructure + public operator fun Tensor.plus(other: Tensor): Tensor /** * Adds the scalar [value] to each element of this tensor. * * @param value the number to be added to each element of this tensor. */ - public operator fun TensorStructure.plusAssign(value: T): Unit + public operator fun Tensor.plusAssign(value: T): Unit /** * Each element of the tensor [other] is added to each element of this tensor. * * @param other tensor to be added. */ - public operator fun TensorStructure.plusAssign(other: TensorStructure): Unit + public operator fun Tensor.plusAssign(other: Tensor): Unit /** @@ -70,7 +70,7 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be subtracted. * @return the difference between this value and tensor [other]. */ - public operator fun T.minus(other: TensorStructure): TensorStructure + public operator fun T.minus(other: Tensor): Tensor /** * Subtracts the scalar [value] from each element of this tensor and returns a new resulting tensor. @@ -78,7 +78,7 @@ public interface TensorAlgebra: Algebra> { * @param value the number to be subtracted from each element of this tensor. * @return the difference between this tensor and [value]. */ - public operator fun TensorStructure.minus(value: T): TensorStructure + public operator fun Tensor.minus(value: T): Tensor /** * Each element of the tensor [other] is subtracted from each element of this tensor. @@ -87,21 +87,21 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be subtracted. * @return the difference between this tensor and [other]. */ - public operator fun TensorStructure.minus(other: TensorStructure): TensorStructure + public operator fun Tensor.minus(other: Tensor): Tensor /** * Subtracts the scalar [value] from each element of this tensor. * * @param value the number to be subtracted from each element of this tensor. */ - public operator fun TensorStructure.minusAssign(value: T): Unit + public operator fun Tensor.minusAssign(value: T): Unit /** * Each element of the tensor [other] is subtracted from each element of this tensor. * * @param other tensor to be subtracted. */ - public operator fun TensorStructure.minusAssign(other: TensorStructure): Unit + public operator fun Tensor.minusAssign(other: Tensor): Unit /** @@ -111,7 +111,7 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be multiplied. * @return the product of this value and tensor [other]. */ - public operator fun T.times(other: TensorStructure): TensorStructure + public operator fun T.times(other: Tensor): Tensor /** * Multiplies the scalar [value] by each element of this tensor and returns a new resulting tensor. @@ -119,7 +119,7 @@ public interface TensorAlgebra: Algebra> { * @param value the number to be multiplied by each element of this tensor. * @return the product of this tensor and [value]. */ - public operator fun TensorStructure.times(value: T): TensorStructure + public operator fun Tensor.times(value: T): Tensor /** * Each element of the tensor [other] is multiplied by each element of this tensor. @@ -128,28 +128,28 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be multiplied. * @return the product of this tensor and [other]. */ - public operator fun TensorStructure.times(other: TensorStructure): TensorStructure + public operator fun Tensor.times(other: Tensor): Tensor /** * Multiplies the scalar [value] by each element of this tensor. * * @param value the number to be multiplied by each element of this tensor. */ - public operator fun TensorStructure.timesAssign(value: T): Unit + public operator fun Tensor.timesAssign(value: T): Unit /** * Each element of the tensor [other] is multiplied by each element of this tensor. * * @param other tensor to be multiplied. */ - public operator fun TensorStructure.timesAssign(other: TensorStructure): Unit + public operator fun Tensor.timesAssign(other: Tensor): Unit /** * Numerical negative, element-wise. * * @return tensor negation of the original tensor. */ - public operator fun TensorStructure.unaryMinus(): TensorStructure + public operator fun Tensor.unaryMinus(): Tensor /** * Returns the tensor at index i @@ -158,7 +158,7 @@ public interface TensorAlgebra: Algebra> { * @param i index of the extractable tensor * @return subtensor of the original tensor with index [i] */ - public operator fun TensorStructure.get(i: Int): TensorStructure + public operator fun Tensor.get(i: Int): Tensor /** * Returns a tensor that is a transposed version of this tensor. The given dimensions [i] and [j] are swapped. @@ -168,7 +168,7 @@ public interface TensorAlgebra: Algebra> { * @param j the second dimension to be transposed * @return transposed tensor */ - public fun TensorStructure.transpose(i: Int = -2, j: Int = -1): TensorStructure + public fun Tensor.transpose(i: Int = -2, j: Int = -1): Tensor /** * Returns a new tensor with the same data as the self tensor but of a different shape. @@ -178,7 +178,7 @@ public interface TensorAlgebra: Algebra> { * @param shape the desired size * @return tensor with new shape */ - public fun TensorStructure.view(shape: IntArray): TensorStructure + public fun Tensor.view(shape: IntArray): Tensor /** * View this tensor as the same size as [other]. @@ -188,7 +188,7 @@ public interface TensorAlgebra: Algebra> { * @param other the result tensor has the same size as other. * @return the result tensor with the same size as other. */ - public fun TensorStructure.viewAs(other: TensorStructure): TensorStructure + public fun Tensor.viewAs(other: Tensor): Tensor /** * Matrix product of two tensors. @@ -219,7 +219,7 @@ public interface TensorAlgebra: Algebra> { * @param other tensor to be multiplied * @return mathematical product of two tensors */ - public infix fun TensorStructure.dot(other: TensorStructure): TensorStructure + public infix fun Tensor.dot(other: Tensor): Tensor /** * Creates a tensor whose diagonals of certain 2D planes (specified by [dim1] and [dim2]) @@ -245,10 +245,10 @@ public interface TensorAlgebra: Algebra> { * are filled by [diagonalEntries] */ public fun diagonalEmbedding( - diagonalEntries: TensorStructure, + diagonalEntries: Tensor, offset: Int = 0, dim1: Int = -2, dim2: Int = -1 - ): TensorStructure + ): Tensor } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt index eccc6fa0d..921157963 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.api /** - * Algebra over a field with partial division on [TensorStructure]. + * Algebra over a field with partial division on [Tensor]. * For more information: https://proofwiki.org/wiki/Definition:Division_Algebra * * @param T the type of items closed under division in the tensors. @@ -21,7 +21,7 @@ public interface TensorPartialDivisionAlgebra : * @param other tensor to divide by. * @return the division of this value by the tensor [other]. */ - public operator fun T.div(other: TensorStructure): TensorStructure + public operator fun T.div(other: Tensor): Tensor /** * Divide by the scalar [value] each element of this tensor returns a new resulting tensor. @@ -29,7 +29,7 @@ public interface TensorPartialDivisionAlgebra : * @param value the number to divide by each element of this tensor. * @return the division of this tensor by the [value]. */ - public operator fun TensorStructure.div(value: T): TensorStructure + public operator fun Tensor.div(value: T): Tensor /** * Each element of the tensor [other] is divided by each element of this tensor. @@ -38,19 +38,19 @@ public interface TensorPartialDivisionAlgebra : * @param other tensor to be divided by. * @return the division of this tensor by [other]. */ - public operator fun TensorStructure.div(other: TensorStructure): TensorStructure + public operator fun Tensor.div(other: Tensor): Tensor /** * Divides by the scalar [value] each element of this tensor. * * @param value the number to divide by each element of this tensor. */ - public operator fun TensorStructure.divAssign(value: T) + public operator fun Tensor.divAssign(value: T) /** * Each element of this tensor is divided by each element of the [other] tensor. * * @param other tensor to be divide by. */ - public operator fun TensorStructure.divAssign(other: TensorStructure) + public operator fun Tensor.divAssign(other: Tensor) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 9541a97f9..d0882efb8 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.structures.* -import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure @@ -10,7 +10,7 @@ public open class BufferedTensor( override val shape: IntArray, internal val mutableBuffer: MutableBuffer, internal val bufferStart: Int -) : TensorStructure { +) : Tensor { public val linearStructure: TensorLinearStructure get() = TensorLinearStructure(shape) @@ -53,33 +53,33 @@ internal fun BufferedTensor.asTensor(): IntTensor = internal fun BufferedTensor.asTensor(): DoubleTensor = DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) -internal fun TensorStructure.copyToBufferedTensor(): BufferedTensor = +internal fun Tensor.copyToBufferedTensor(): BufferedTensor = BufferedTensor( this.shape, TensorLinearStructure(this.shape).indices().map(this::get).toMutableList().asMutableBuffer(), 0 ) -internal fun TensorStructure.toBufferedTensor(): BufferedTensor = when (this) { +internal fun Tensor.toBufferedTensor(): BufferedTensor = when (this) { is BufferedTensor -> this is MutableBufferND -> if (this.strides.strides contentEquals TensorLinearStructure(this.shape).strides) BufferedTensor(this.shape, this.mutableBuffer, 0) else this.copyToBufferedTensor() else -> this.copyToBufferedTensor() } -internal val TensorStructure.tensor: DoubleTensor +internal val Tensor.tensor: DoubleTensor get() = when (this) { is DoubleTensor -> this else -> this.toBufferedTensor().asTensor() } -internal val TensorStructure.tensor: IntTensor +internal val Tensor.tensor: IntTensor get() = when (this) { is IntTensor -> this else -> this.toBufferedTensor().asTensor() } -public fun TensorStructure.toDoubleTensor(): DoubleTensor = this.tensor -public fun TensorStructure.toIntTensor(): IntTensor = this.tensor +public fun Tensor.toDoubleTensor(): DoubleTensor = this.tensor +public fun Tensor.toIntTensor(): IntTensor = this.tensor public fun Array.toDoubleTensor(): DoubleTensor { val n = size diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt index 9b97d5ef2..873ec9027 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core.algebras -import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.broadcastTensors import space.kscience.kmath.tensors.core.broadcastTo @@ -16,7 +16,7 @@ import space.kscience.kmath.tensors.core.broadcastTo */ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { - override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { + override fun Tensor.plus(other: Tensor): DoubleTensor { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] @@ -26,7 +26,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun TensorStructure.plusAssign(other: TensorStructure) { + override fun Tensor.plusAssign(other: Tensor) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] += @@ -34,7 +34,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { } } - override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { + override fun Tensor.minus(other: Tensor): DoubleTensor { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] @@ -44,7 +44,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun TensorStructure.minusAssign(other: TensorStructure) { + override fun Tensor.minusAssign(other: Tensor) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] -= @@ -52,7 +52,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { } } - override fun TensorStructure.times(other: TensorStructure): DoubleTensor { + override fun Tensor.times(other: Tensor): DoubleTensor { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] @@ -63,7 +63,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun TensorStructure.timesAssign(other: TensorStructure) { + override fun Tensor.timesAssign(other: Tensor) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] *= @@ -71,7 +71,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { } } - override fun TensorStructure.div(other: TensorStructure): DoubleTensor { + override fun Tensor.div(other: Tensor): DoubleTensor { val broadcast = broadcastTensors(tensor, other.tensor) val newThis = broadcast[0] val newOther = broadcast[1] @@ -82,7 +82,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { return DoubleTensor(newThis.shape, resBuffer) } - override fun TensorStructure.divAssign(other: TensorStructure) { + override fun Tensor.divAssign(other: Tensor) { val newOther = broadcastTo(other.tensor, tensor.shape) for (i in 0 until tensor.linearStructure.linearSize) { tensor.mutableBuffer.array()[tensor.bufferStart + i] /= diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 4a942df84..9aa6f093e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors.core.algebras import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra -import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.tensor import kotlin.math.* @@ -14,38 +14,38 @@ import kotlin.math.* public object DoubleAnalyticTensorAlgebra : AnalyticTensorAlgebra, DoubleTensorAlgebra() { - override fun TensorStructure.exp(): DoubleTensor = tensor.map(::exp) + override fun Tensor.exp(): DoubleTensor = tensor.map(::exp) - override fun TensorStructure.log(): DoubleTensor = tensor.map(::ln) + override fun Tensor.log(): DoubleTensor = tensor.map(::ln) - override fun TensorStructure.sqrt(): DoubleTensor = tensor.map(::sqrt) + override fun Tensor.sqrt(): DoubleTensor = tensor.map(::sqrt) - override fun TensorStructure.cos(): DoubleTensor = tensor.map(::cos) + override fun Tensor.cos(): DoubleTensor = tensor.map(::cos) - override fun TensorStructure.acos(): DoubleTensor = tensor.map(::acos) + override fun Tensor.acos(): DoubleTensor = tensor.map(::acos) - override fun TensorStructure.cosh(): DoubleTensor = tensor.map(::cosh) + override fun Tensor.cosh(): DoubleTensor = tensor.map(::cosh) - override fun TensorStructure.acosh(): DoubleTensor = tensor.map(::acosh) + override fun Tensor.acosh(): DoubleTensor = tensor.map(::acosh) - override fun TensorStructure.sin(): DoubleTensor = tensor.map(::sin) + override fun Tensor.sin(): DoubleTensor = tensor.map(::sin) - override fun TensorStructure.asin(): DoubleTensor = tensor.map(::asin) + override fun Tensor.asin(): DoubleTensor = tensor.map(::asin) - override fun TensorStructure.sinh(): DoubleTensor = tensor.map(::sinh) + override fun Tensor.sinh(): DoubleTensor = tensor.map(::sinh) - override fun TensorStructure.asinh(): DoubleTensor = tensor.map(::asinh) + override fun Tensor.asinh(): DoubleTensor = tensor.map(::asinh) - override fun TensorStructure.tan(): DoubleTensor = tensor.map(::tan) + override fun Tensor.tan(): DoubleTensor = tensor.map(::tan) - override fun TensorStructure.atan(): DoubleTensor = tensor.map(::atan) + override fun Tensor.atan(): DoubleTensor = tensor.map(::atan) - override fun TensorStructure.tanh(): DoubleTensor = tensor.map(::tanh) + override fun Tensor.tanh(): DoubleTensor = tensor.map(::tanh) - override fun TensorStructure.atanh(): DoubleTensor = tensor.map(::atanh) + override fun Tensor.atanh(): DoubleTensor = tensor.map(::atanh) - override fun TensorStructure.ceil(): DoubleTensor = tensor.map(::ceil) + override fun Tensor.ceil(): DoubleTensor = tensor.map(::ceil) - override fun TensorStructure.floor(): DoubleTensor = tensor.map(::floor) + override fun Tensor.floor(): DoubleTensor = tensor.map(::floor) } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index dd5ad5a61..89345e315 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.tensors.core.algebras import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D -import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.checkSquareMatrix import space.kscience.kmath.tensors.core.choleskyHelper @@ -25,19 +25,19 @@ public object DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, DoubleTensorAlgebra() { - override fun TensorStructure.inv(): DoubleTensor = invLU(1e-9) + override fun Tensor.inv(): DoubleTensor = invLU(1e-9) - override fun TensorStructure.det(): DoubleTensor = detLU(1e-9) + override fun Tensor.det(): DoubleTensor = detLU(1e-9) - public fun TensorStructure.luFactor(epsilon: Double): Pair = + public fun Tensor.luFactor(epsilon: Double): Pair = computeLU(tensor, epsilon) ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") - public fun TensorStructure.luFactor(): Pair = luFactor(1e-9) + public fun Tensor.luFactor(): Pair = luFactor(1e-9) public fun luPivot( - luTensor: TensorStructure, - pivotsTensor: TensorStructure + luTensor: Tensor, + pivotsTensor: Tensor ): Triple { checkSquareMatrix(luTensor.shape) check( @@ -66,7 +66,7 @@ public object DoubleLinearOpsTensorAlgebra : return Triple(pTensor, lTensor, uTensor) } - public fun TensorStructure.cholesky(epsilon: Double): DoubleTensor { + public fun Tensor.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) checkPositiveDefinite(tensor, epsilon) @@ -79,9 +79,9 @@ public object DoubleLinearOpsTensorAlgebra : return lTensor } - override fun TensorStructure.cholesky(): DoubleTensor = cholesky(1e-6) + override fun Tensor.cholesky(): DoubleTensor = cholesky(1e-6) - override fun TensorStructure.qr(): Pair { + override fun Tensor.qr(): Pair { checkSquareMatrix(shape) val qTensor = zeroesLike() val rTensor = zeroesLike() @@ -95,10 +95,10 @@ public object DoubleLinearOpsTensorAlgebra : return qTensor to rTensor } - override fun TensorStructure.svd(): Triple = + override fun Tensor.svd(): Triple = svd(epsilon = 1e-10) - public fun TensorStructure.svd(epsilon: Double): Triple { + public fun Tensor.svd(epsilon: Double): Triple { val size = tensor.linearStructure.dim val commonShape = tensor.shape.sliceArray(0 until size - 2) val (n, m) = tensor.shape.sliceArray(size - 2 until size) @@ -122,11 +122,11 @@ public object DoubleLinearOpsTensorAlgebra : return Triple(uTensor.transpose(), sTensor, vTensor.transpose()) } - override fun TensorStructure.symEig(): Pair = + override fun Tensor.symEig(): Pair = symEig(epsilon = 1e-15) //For information: http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html - public fun TensorStructure.symEig(epsilon: Double): Pair { + public fun Tensor.symEig(epsilon: Double): Pair { checkSymmetric(tensor, epsilon) val (u, s, v) = tensor.svd(epsilon) val shp = s.shape + intArrayOf(1) @@ -139,7 +139,7 @@ public object DoubleLinearOpsTensorAlgebra : return eig to v } - public fun TensorStructure.detLU(epsilon: Double = 1e-9): DoubleTensor { + public fun Tensor.detLU(epsilon: Double = 1e-9): DoubleTensor { checkSquareMatrix(tensor.shape) val luTensor = tensor.copy() @@ -164,7 +164,7 @@ public object DoubleLinearOpsTensorAlgebra : return detTensor } - public fun TensorStructure.invLU(epsilon: Double = 1e-9): DoubleTensor { + public fun Tensor.invLU(epsilon: Double = 1e-9): DoubleTensor { val (luTensor, pivotsTensor) = luFactor(epsilon) val invTensor = luTensor.zeroesLike() @@ -177,11 +177,11 @@ public object DoubleLinearOpsTensorAlgebra : return invTensor } - public fun TensorStructure.lu(epsilon: Double = 1e-9): Triple { + public fun Tensor.lu(epsilon: Double = 1e-9): Triple { val (lu, pivots) = this.luFactor(epsilon) return luPivot(lu, pivots) } - override fun TensorStructure.lu(): Triple = lu(1e-9) + override fun Tensor.lu(): Triple = lu(1e-9) } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index d3e8bf175..4009f7b45 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.tensors.core.algebras import space.kscience.kmath.nd.as2D import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra -import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.broadcastOuterTensors import space.kscience.kmath.tensors.core.checkBufferShapeConsistency @@ -25,7 +25,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public companion object : DoubleTensorAlgebra() - override fun TensorStructure.value(): Double { + override fun Tensor.value(): Double { check(tensor.shape contentEquals intArrayOf(1)) { "Inconsistent value for tensor of shape ${shape.toList()}" } @@ -39,7 +39,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(shape, buffer, 0) } - override operator fun TensorStructure.get(i: Int): DoubleTensor { + override operator fun Tensor.get(i: Int): DoubleTensor { val lastShape = tensor.shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) val newStart = newShape.reduce(Int::times) * i + tensor.bufferStart @@ -52,7 +52,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(shape, buffer) } - public fun TensorStructure.fullLike(value: Double): DoubleTensor { + public fun Tensor.fullLike(value: Double): DoubleTensor { val shape = tensor.shape val buffer = DoubleArray(tensor.numElements) { value } return DoubleTensor(shape, buffer) @@ -60,11 +60,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun zeros(shape: IntArray): DoubleTensor = full(0.0, shape) - public fun TensorStructure.zeroesLike(): DoubleTensor = tensor.fullLike(0.0) + public fun Tensor.zeroesLike(): DoubleTensor = tensor.fullLike(0.0) public fun ones(shape: IntArray): DoubleTensor = full(1.0, shape) - public fun TensorStructure.onesLike(): DoubleTensor = tensor.fullLike(1.0) + public fun Tensor.onesLike(): DoubleTensor = tensor.fullLike(1.0) public fun eye(n: Int): DoubleTensor { val shape = intArrayOf(n, n) @@ -76,20 +76,20 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return res } - public fun TensorStructure.copy(): DoubleTensor { + public fun Tensor.copy(): DoubleTensor { return DoubleTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart) } - override fun Double.plus(other: TensorStructure): DoubleTensor { + override fun Double.plus(other: Tensor): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] + this } return DoubleTensor(other.shape, resBuffer) } - override fun TensorStructure.plus(value: Double): DoubleTensor = value + tensor + override fun Tensor.plus(value: Double): DoubleTensor = value + tensor - override fun TensorStructure.plus(other: TensorStructure): DoubleTensor { + override fun Tensor.plus(other: Tensor): DoubleTensor { checkShapesCompatible(tensor, other.tensor) val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[i] + other.tensor.mutableBuffer.array()[i] @@ -97,13 +97,13 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(tensor.shape, resBuffer) } - override fun TensorStructure.plusAssign(value: Double) { + override fun Tensor.plusAssign(value: Double) { for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] += value } } - override fun TensorStructure.plusAssign(other: TensorStructure) { + override fun Tensor.plusAssign(other: Tensor) { checkShapesCompatible(tensor, other.tensor) for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] += @@ -111,21 +111,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } } - override fun Double.minus(other: TensorStructure): DoubleTensor { + override fun Double.minus(other: Tensor): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> this - other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } - override fun TensorStructure.minus(value: Double): DoubleTensor { + override fun Tensor.minus(value: Double): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[tensor.bufferStart + i] - value } return DoubleTensor(tensor.shape, resBuffer) } - override fun TensorStructure.minus(other: TensorStructure): DoubleTensor { + override fun Tensor.minus(other: Tensor): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[i] - other.tensor.mutableBuffer.array()[i] @@ -133,13 +133,13 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(tensor.shape, resBuffer) } - override fun TensorStructure.minusAssign(value: Double) { + override fun Tensor.minusAssign(value: Double) { for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] -= value } } - override fun TensorStructure.minusAssign(other: TensorStructure) { + override fun Tensor.minusAssign(other: Tensor) { checkShapesCompatible(tensor, other) for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] -= @@ -147,16 +147,16 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } } - override fun Double.times(other: TensorStructure): DoubleTensor { + override fun Double.times(other: Tensor): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] * this } return DoubleTensor(other.shape, resBuffer) } - override fun TensorStructure.times(value: Double): DoubleTensor = value * tensor + override fun Tensor.times(value: Double): DoubleTensor = value * tensor - override fun TensorStructure.times(other: TensorStructure): DoubleTensor { + override fun Tensor.times(other: Tensor): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[tensor.bufferStart + i] * @@ -165,13 +165,13 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(tensor.shape, resBuffer) } - override fun TensorStructure.timesAssign(value: Double) { + override fun Tensor.timesAssign(value: Double) { for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] *= value } } - override fun TensorStructure.timesAssign(other: TensorStructure) { + override fun Tensor.timesAssign(other: Tensor) { checkShapesCompatible(tensor, other) for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] *= @@ -179,21 +179,21 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } } - override fun Double.div(other: TensorStructure): DoubleTensor { + override fun Double.div(other: Tensor): DoubleTensor { val resBuffer = DoubleArray(other.tensor.numElements) { i -> this / other.tensor.mutableBuffer.array()[other.tensor.bufferStart + i] } return DoubleTensor(other.shape, resBuffer) } - override fun TensorStructure.div(value: Double): DoubleTensor { + override fun Tensor.div(value: Double): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[tensor.bufferStart + i] / value } return DoubleTensor(shape, resBuffer) } - override fun TensorStructure.div(other: TensorStructure): DoubleTensor { + override fun Tensor.div(other: Tensor): DoubleTensor { checkShapesCompatible(tensor, other) val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[other.tensor.bufferStart + i] / @@ -202,13 +202,13 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(tensor.shape, resBuffer) } - override fun TensorStructure.divAssign(value: Double) { + override fun Tensor.divAssign(value: Double) { for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] /= value } } - override fun TensorStructure.divAssign(other: TensorStructure) { + override fun Tensor.divAssign(other: Tensor) { checkShapesCompatible(tensor, other) for (i in 0 until tensor.numElements) { tensor.mutableBuffer.array()[tensor.bufferStart + i] /= @@ -216,14 +216,14 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } } - override fun TensorStructure.unaryMinus(): DoubleTensor { + override fun Tensor.unaryMinus(): DoubleTensor { val resBuffer = DoubleArray(tensor.numElements) { i -> tensor.mutableBuffer.array()[tensor.bufferStart + i].unaryMinus() } return DoubleTensor(tensor.shape, resBuffer) } - override fun TensorStructure.transpose(i: Int, j: Int): DoubleTensor { + override fun Tensor.transpose(i: Int, j: Int): DoubleTensor { val ii = tensor.minusIndex(i) val jj = tensor.minusIndex(j) checkTranspose(tensor.dimension, ii, jj) @@ -248,16 +248,16 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } - override fun TensorStructure.view(shape: IntArray): DoubleTensor { + override fun Tensor.view(shape: IntArray): DoubleTensor { checkView(tensor, shape) return DoubleTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart) } - override fun TensorStructure.viewAs(other: TensorStructure): DoubleTensor { + override fun Tensor.viewAs(other: Tensor): DoubleTensor { return tensor.view(other.shape) } - override infix fun TensorStructure.dot(other: TensorStructure): DoubleTensor { + override infix fun Tensor.dot(other: Tensor): DoubleTensor { if (tensor.shape.size == 1 && other.shape.size == 1) { return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.mutableBuffer.array().sum())) } @@ -309,7 +309,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return resTensor } - override fun diagonalEmbedding(diagonalEntries: TensorStructure, offset: Int, dim1: Int, dim2: Int): + override fun diagonalEmbedding(diagonalEntries: Tensor, offset: Int, dim1: Int, dim2: Int): DoubleTensor { val n = diagonalEntries.shape.size val d1 = minusIndexFrom(n + 1, dim1) @@ -358,7 +358,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } - public fun TensorStructure.map(transform: (Double) -> Double): DoubleTensor { + public fun Tensor.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( tensor.shape, tensor.mutableBuffer.array().map { transform(it) }.toDoubleArray(), @@ -366,14 +366,14 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { ) } - public fun TensorStructure.eq(other: TensorStructure, epsilon: Double): Boolean { + public fun Tensor.eq(other: Tensor, epsilon: Double): Boolean { return tensor.eq(other) { x, y -> abs(x - y) < epsilon } } - public infix fun TensorStructure.eq(other: TensorStructure): Boolean = tensor.eq(other, 1e-5) + public infix fun Tensor.eq(other: Tensor): Boolean = tensor.eq(other, 1e-5) - private fun TensorStructure.eq( - other: TensorStructure, + private fun Tensor.eq( + other: Tensor, eqFunction: (Double, Double) -> Boolean ): Boolean { checkShapesCompatible(tensor, other) @@ -396,7 +396,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun randomNormal(shape: IntArray, seed: Long = 0): DoubleTensor = DoubleTensor(shape, getRandomNormals(shape.reduce(Int::times), seed)) - public fun TensorStructure.randomNormalLike(seed: Long = 0): DoubleTensor = + public fun Tensor.randomNormalLike(seed: Long = 0): DoubleTensor = DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) // stack tensors by axis 0 @@ -412,7 +412,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } // build tensor from this rows by given indices - public fun TensorStructure.rowsByIndices(indices: IntArray): DoubleTensor { + public fun Tensor.rowsByIndices(indices: IntArray): DoubleTensor { return stack(indices.map { this[it] }) } } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt index b1c12ccde..f8bd5027a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt @@ -1,6 +1,6 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.tensors.api.TensorStructure +import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra @@ -20,7 +20,7 @@ internal fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray) = "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" } -internal fun checkShapesCompatible(a: TensorStructure, b: TensorStructure) = +internal fun checkShapesCompatible(a: Tensor, b: Tensor) = check(a.shape contentEquals b.shape) { "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " } @@ -30,7 +30,7 @@ internal fun checkTranspose(dim: Int, i: Int, j: Int) = "Cannot transpose $i to $j for a tensor of dim $dim" } -internal fun checkView(a: TensorStructure, shape: IntArray) = +internal fun checkView(a: Tensor, shape: IntArray) = check(a.shape.reduce(Int::times) == shape.reduce(Int::times)) internal fun checkSquareMatrix(shape: IntArray) { @@ -44,7 +44,7 @@ internal fun checkSquareMatrix(shape: IntArray) { } internal fun DoubleTensorAlgebra.checkSymmetric( - tensor: TensorStructure, epsilon: Double = 1e-6 + tensor: Tensor, epsilon: Double = 1e-6 ) = check(tensor.eq(tensor.transpose(), epsilon)) { "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" From f0627b2ced8cba0c641cb40a0bd10184b336b657 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 3 May 2021 00:24:32 +0700 Subject: [PATCH 278/393] Simplify and revise test cases for MST compilation engines #285 --- ...TestCompilerConsistencyWithInterpreter.kt} | 24 ++--- .../kmath/ast/TestCompilerOperations.kt | 65 +++++++++++++ .../kmath/ast/TestCompilerVariables.kt} | 14 +-- .../ast/{ParserTest.kt => TestParser.kt} | 2 +- ...cedenceTest.kt => TestParserPrecedence.kt} | 2 +- .../kotlin/space/kscience/kmath/ast/utils.kt | 25 +++++ .../kotlin/space/kscience/kmath/ast/utils.kt | 39 ++++++++ .../TestESTreeConsistencyWithInterpreter.kt | 97 ------------------- .../estree/TestESTreeOperationsSupport.kt | 42 -------- .../kmath/estree/TestESTreeSpecialization.kt | 76 --------------- .../kmath/estree/TestESTreeVariables.kt | 34 ------- .../kmath/wasm/TestWasmOperationsSupport.kt | 42 -------- .../kmath/wasm/TestWasmSpecialization.kt | 76 --------------- .../asm/TestAsmConsistencyWithInterpreter.kt | 97 ------------------- .../kmath/asm/TestAsmOperationsSupport.kt | 42 -------- .../kmath/asm/TestAsmSpecialization.kt | 76 --------------- .../kscience/kmath/asm/TestAsmVariables.kt | 34 ------- .../kotlin/space/kscience/kmath/ast/utils.kt | 25 +++++ 18 files changed, 171 insertions(+), 641 deletions(-) rename kmath-ast/src/{jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt => commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt} (76%) create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt rename kmath-ast/src/{jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt => commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt} (76%) rename kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/{ParserTest.kt => TestParser.kt} (98%) rename kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/{ParserPrecedenceTest.kt => TestParserPrecedence.kt} (96%) create mode 100644 kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt create mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt delete mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt delete mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt delete mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt delete mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt delete mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt delete mode 100644 kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt delete mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt create mode 100644 kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt similarity index 76% rename from kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt index f3e0726d6..0d018070c 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmConsistencyWithInterpreter.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt @@ -3,12 +3,12 @@ * 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.wasm +package space.kscience.kmath.ast import space.kscience.kmath.expressions.MstField import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.interpret -import space.kscience.kmath.misc.symbol +import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing import space.kscience.kmath.operations.bindSymbol @@ -16,45 +16,41 @@ import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals -internal class TestWasmConsistencyWithInterpreter { +internal class TestCompilerConsistencyWithInterpreter { @Test - fun intRing() { + fun intRing() = runCompilerTest { val mst = MstRing { binaryOperationFunction("+")( unaryOperationFunction("+")( (bindSymbol(x) - (2.toByte() + (scale( add(number(1), number(1)), - 2.0 + 2.0, ) + 1.toByte()))) * 3.0 - 1.toByte() ), - number(1) + number(1), ) * number(2) } assertEquals( mst.interpret(IntRing, x to 3), - mst.compile(IntRing, x to 3) + mst.compile(IntRing, x to 3), ) } @Test - fun doubleField() { + fun doubleField() = runCompilerTest { val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), - number(1) / 2 + number(2.0) * one + number(1) / 2 + number(2.0) * one, ) + zero } assertEquals( mst.interpret(DoubleField, x to 2.0), - mst.compile(DoubleField, x to 2.0) + mst.compile(DoubleField, x to 2.0), ) } - - private companion object { - private val x by symbol - } } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt new file mode 100644 index 000000000..7d2af31c2 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt @@ -0,0 +1,65 @@ +/* + * 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.ast + +import space.kscience.kmath.expressions.MstExtendedField +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.misc.Symbol.Companion.x +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.bindSymbol +import space.kscience.kmath.operations.invoke +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class TestCompilerOperations { + @Test + fun testUnaryPlus() = runCompilerTest { + val expr = MstExtendedField { +bindSymbol(x) }.compileToExpression(DoubleField) + assertEquals(2.0, expr(x to 2.0)) + } + + @Test + fun testUnaryMinus() = runCompilerTest { + val expr = MstExtendedField { -bindSymbol(x) }.compileToExpression(DoubleField) + assertEquals(-2.0, expr(x to 2.0)) + } + + @Test + fun testAdd() = runCompilerTest { + val expr = MstExtendedField { bindSymbol(x) + bindSymbol(x) }.compileToExpression(DoubleField) + assertEquals(4.0, expr(x to 2.0)) + } + + @Test + fun testSine() = runCompilerTest { + val expr = MstExtendedField { sin(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(0.0, expr(x to 0.0)) + } + + @Test + fun testCosine() = runCompilerTest { + val expr = MstExtendedField { cos(bindSymbol(x)) }.compileToExpression(DoubleField) + assertEquals(1.0, expr(x to 0.0)) + } + + @Test + fun testSubtract() = runCompilerTest { + val expr = MstExtendedField { bindSymbol(x) - bindSymbol(x) }.compileToExpression(DoubleField) + assertEquals(0.0, expr(x to 2.0)) + } + + @Test + fun testDivide() = runCompilerTest { + val expr = MstExtendedField { bindSymbol(x) / bindSymbol(x) }.compileToExpression(DoubleField) + assertEquals(1.0, expr(x to 2.0)) + } + + @Test + fun testPower() = runCompilerTest { + val expr = MstExtendedField { bindSymbol(x) pow 2 }.compileToExpression(DoubleField) + assertEquals(4.0, expr(x to 2.0)) + } +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt similarity index 76% rename from kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt index 406ba8c8d..ecf8ed367 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmVariables.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt @@ -3,11 +3,11 @@ * 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.wasm +package space.kscience.kmath.ast import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol +import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.IntRing import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke @@ -15,20 +15,16 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith -internal class TestWasmVariables { +internal class TestCompilerVariables { @Test - fun testVariable() { + fun testVariable() = runCompilerTest { val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing) assertEquals(1, expr(x to 1)) } @Test - fun testUndefinedVariableFails() { + fun testUndefinedVariableFails() = runCompilerTest { val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing) assertFailsWith { expr() } } - - private companion object { - private val x by symbol - } } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt similarity index 98% rename from kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt index 185659a1f..b838245e1 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt @@ -13,7 +13,7 @@ import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals -internal class ParserTest { +internal class TestParser { @Test fun evaluateParsedMst() { val mst = "2+2*(2+2)".parseMath() diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt similarity index 96% rename from kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt rename to kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt index 67d77839a..bb6bb3ce1 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/ParserPrecedenceTest.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt @@ -10,7 +10,7 @@ import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals -internal class ParserPrecedenceTest { +internal class TestParserPrecedence { @Test fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath())) diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt new file mode 100644 index 000000000..abeaed0f8 --- /dev/null +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -0,0 +1,25 @@ +/* + * 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.ast + +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.IntRing + +internal interface CompilerTestContext { + fun MST.compileToExpression(algebra: IntRing): Expression + fun MST.compile(algebra: IntRing, arguments: Map): Int + fun MST.compile(algebra: IntRing, vararg arguments: Pair): Int = compile(algebra, mapOf(*arguments)) + fun MST.compileToExpression(algebra: DoubleField): Expression + fun MST.compile(algebra: DoubleField, arguments: Map): Double + + fun MST.compile(algebra: DoubleField, vararg arguments: Pair): Double = + compile(algebra, mapOf(*arguments)) +} + +internal expect inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt new file mode 100644 index 000000000..6b5b1b83d --- /dev/null +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -0,0 +1,39 @@ +/* + * 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.ast + +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.estree.compile as estreeCompile +import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression +import space.kscience.kmath.wasm.compile as wasmCompile +import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression + +private object WasmCompilerTestContext : CompilerTestContext { + override fun MST.compileToExpression(algebra: IntRing): Expression = wasmCompileToExpression(algebra) + override fun MST.compile(algebra: IntRing, arguments: Map): Int = wasmCompile(algebra, arguments) + override fun MST.compileToExpression(algebra: DoubleField): Expression = wasmCompileToExpression(algebra) + + override fun MST.compile(algebra: DoubleField, arguments: Map): Double = + wasmCompile(algebra, arguments) +} + +private object ESTreeCompilerTestContext : CompilerTestContext { + override fun MST.compileToExpression(algebra: IntRing): Expression = estreeCompileToExpression(algebra) + override fun MST.compile(algebra: IntRing, arguments: Map): Int = estreeCompile(algebra, arguments) + override fun MST.compileToExpression(algebra: DoubleField): Expression = estreeCompileToExpression(algebra) + + override fun MST.compile(algebra: DoubleField, arguments: Map): Double = + estreeCompile(algebra, arguments) +} + +internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) { + action(WasmCompilerTestContext) + action(ESTreeCompilerTestContext) +} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt deleted file mode 100644 index d80318db8..000000000 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeConsistencyWithInterpreter.kt +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.estree - -import space.kscience.kmath.complex.ComplexField -import space.kscience.kmath.complex.toComplex -import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.ByteRing -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestESTreeConsistencyWithInterpreter { - @Test - fun mstSpace() { - val mst = MstGroup { - binaryOperationFunction("+")( - unaryOperationFunction("+")( - number(3.toByte()) - (number(2.toByte()) + (scale( - add(number(1), number(1)), - 2.0 - ) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) - ), - - number(1) - ) + bindSymbol(x) + zero - } - - assertEquals( - mst.interpret(MstGroup, x to MST.Numeric(2)), - mst.compile(MstGroup, x to MST.Numeric(2)) - ) - } - - @Test - fun byteRing() { - val mst = MstRing { - binaryOperationFunction("+")( - unaryOperationFunction("+")( - (bindSymbol(x) - (2.toByte() + (scale( - add(number(1), number(1)), - 2.0 - ) + 1.toByte()))) * 3.0 - 1.toByte() - ), - - number(1) - ) * number(2) - } - - assertEquals( - mst.interpret(ByteRing, x to 3.toByte()), - mst.compile(ByteRing, x to 3.toByte()) - ) - } - - @Test - fun doubleField() { - val mst = MstField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 - + number(1), - number(1) / 2 + number(2.0) * one - ) + zero - } - - assertEquals( - mst.interpret(DoubleField, x to 2.0), - mst.compile(DoubleField, x to 2.0) - ) - } - - @Test - fun complexField() { - val mst = MstField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 - + number(1), - number(1) / 2 + number(2.0) * one - ) + zero - } - - assertEquals( - mst.interpret(ComplexField, x to 2.0.toComplex()), - mst.compile(ComplexField, x to 2.0.toComplex()), - ) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt deleted file mode 100644 index a0b68a811..000000000 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeOperationsSupport.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.estree - -import space.kscience.kmath.expressions.MstField -import space.kscience.kmath.expressions.MstGroup -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestESTreeOperationsSupport { - @Test - fun testUnaryOperationInvocation() { - val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField) - val res = expression(x to 2.0) - assertEquals(-2.0, res) - } - - @Test - fun testBinaryOperationInvocation() { - val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField) - val res = expression(x to 2.0) - assertEquals(-1.0, res) - } - - @Test - fun testConstProductInvocation() { - val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0) - assertEquals(4.0, res) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt deleted file mode 100644 index 6756fd8c7..000000000 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeSpecialization.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.estree - -import space.kscience.kmath.expressions.MstExtendedField -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestESTreeSpecialization { - @Test - fun testUnaryPlus() { - val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(2.0, expr(x to 2.0)) - } - - @Test - fun testUnaryMinus() { - val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(-2.0, expr(x to 2.0)) - } - - @Test - fun testAdd() { - val expr = MstExtendedField { - binaryOperationFunction("+")( - bindSymbol(x), - bindSymbol(x), - ) - }.compileToExpression(DoubleField) - assertEquals(4.0, expr(x to 2.0)) - } - - @Test - fun testSine() { - val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(0.0, expr(x to 0.0)) - } - - @Test - fun testSubtract() { - val expr = MstExtendedField { - binaryOperationFunction("-")(bindSymbol(x), - bindSymbol(x)) - }.compileToExpression(DoubleField) - assertEquals(0.0, expr(x to 2.0)) - } - - @Test - fun testDivide() { - val expr = MstExtendedField { - binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x)) - }.compileToExpression(DoubleField) - assertEquals(1.0, expr(x to 2.0)) - } - - @Test - fun testPower() { - val expr = MstExtendedField { - binaryOperationFunction("pow")(bindSymbol(x), number(2)) - }.compileToExpression(DoubleField) - - assertEquals(4.0, expr(x to 2.0)) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt deleted file mode 100644 index e1830d9df..000000000 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/estree/TestESTreeVariables.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.estree - -import space.kscience.kmath.expressions.MstRing -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.ByteRing -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - -internal class TestESTreeVariables { - @Test - fun testVariable() { - val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) - assertEquals(1.toByte(), expr(x to 1.toByte())) - } - - @Test - fun testUndefinedVariableFails() { - val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) - assertFailsWith { expr() } - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt deleted file mode 100644 index 2946592f4..000000000 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmOperationsSupport.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.wasm - -import space.kscience.kmath.expressions.MstField -import space.kscience.kmath.expressions.MstGroup -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestWasmOperationsSupport { - @Test - fun testUnaryOperationInvocation() { - val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField) - val res = expression(x to 2.0) - assertEquals(-2.0, res) - } - - @Test - fun testBinaryOperationInvocation() { - val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField) - val res = expression(x to 2.0) - assertEquals(-1.0, res) - } - - @Test - fun testConstProductInvocation() { - val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0) - assertEquals(4.0, res) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt deleted file mode 100644 index e1f7b603a..000000000 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecialization.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.wasm - -import space.kscience.kmath.expressions.MstExtendedField -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestWasmSpecialization { - @Test - fun testUnaryPlus() { - val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(2.0, expr(x to 2.0)) - } - - @Test - fun testUnaryMinus() { - val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(-2.0, expr(x to 2.0)) - } - - @Test - fun testAdd() { - val expr = MstExtendedField { - binaryOperationFunction("+")( - bindSymbol(x), - bindSymbol(x), - ) - }.compileToExpression(DoubleField) - assertEquals(4.0, expr(x to 2.0)) - } - - @Test - fun testSine() { - val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(0.0, expr(x to 0.0)) - } - - @Test - fun testSubtract() { - val expr = MstExtendedField { - binaryOperationFunction("-")(bindSymbol(x), - bindSymbol(x)) - }.compileToExpression(DoubleField) - assertEquals(0.0, expr(x to 2.0)) - } - - @Test - fun testDivide() { - val expr = MstExtendedField { - binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x)) - }.compileToExpression(DoubleField) - assertEquals(1.0, expr(x to 2.0)) - } - - @Test - fun testPower() { - val expr = MstExtendedField { - binaryOperationFunction("pow")(bindSymbol(x), number(2)) - }.compileToExpression(DoubleField) - - assertEquals(4.0, expr(x to 2.0)) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt deleted file mode 100644 index f94d36602..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmConsistencyWithInterpreter.kt +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.asm - -import space.kscience.kmath.complex.ComplexField -import space.kscience.kmath.complex.toComplex -import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.ByteRing -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestAsmConsistencyWithInterpreter { - @Test - fun mstSpace() { - val mst = MstGroup { - binaryOperationFunction("+")( - unaryOperationFunction("+")( - number(3.toByte()) - (number(2.toByte()) + (scale( - add(number(1), number(1)), - 2.0 - ) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) - ), - - number(1) - ) + bindSymbol(x) + zero - } - - assertEquals( - mst.interpret(MstGroup, x to MST.Numeric(2)), - mst.compile(MstGroup, x to MST.Numeric(2)) - ) - } - - @Test - fun byteRing() { - val mst = MstRing { - binaryOperationFunction("+")( - unaryOperationFunction("+")( - (bindSymbol(x) - (2.toByte() + (scale( - add(number(1), number(1)), - 2.0 - ) + 1.toByte()))) * 3.0 - 1.toByte() - ), - - number(1) - ) * number(2) - } - - assertEquals( - mst.interpret(ByteRing, x to 3.toByte()), - mst.compile(ByteRing, x to 3.toByte()) - ) - } - - @Test - fun doubleField() { - val mst = MstField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 - + number(1), - number(1) / 2 + number(2.0) * one - ) + zero - } - - assertEquals( - mst.interpret(DoubleField, x to 2.0), - mst.compile(DoubleField, x to 2.0) - ) - } - - @Test - fun complexField() { - val mst = MstField { - +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 - + number(1), - number(1) / 2 + number(2.0) * one - ) + zero - } - - assertEquals( - mst.interpret(ComplexField, x to 2.0.toComplex()), - mst.compile(ComplexField, x to 2.0.toComplex()) - ) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt deleted file mode 100644 index 147639f7c..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmOperationsSupport.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.asm - -import space.kscience.kmath.expressions.MstField -import space.kscience.kmath.expressions.MstGroup -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestAsmOperationsSupport { - @Test - fun testUnaryOperationInvocation() { - val expression = MstGroup { -bindSymbol(x) }.compileToExpression(DoubleField) - val res = expression(x to 2.0) - assertEquals(-2.0, res) - } - - @Test - fun testBinaryOperationInvocation() { - val expression = MstGroup { -bindSymbol(x) + number(1.0) }.compileToExpression(DoubleField) - val res = expression(x to 2.0) - assertEquals(-1.0, res) - } - - @Test - fun testConstProductInvocation() { - val res = MstField { bindSymbol(x) * 2 }.compileToExpression(DoubleField)(x to 2.0) - assertEquals(4.0, res) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt deleted file mode 100644 index 3a681e482..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmSpecialization.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.asm - -import space.kscience.kmath.expressions.MstExtendedField -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class TestAsmSpecialization { - @Test - fun testUnaryPlus() { - val expr = MstExtendedField { unaryOperationFunction("+")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(2.0, expr(x to 2.0)) - } - - @Test - fun testUnaryMinus() { - val expr = MstExtendedField { unaryOperationFunction("-")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(-2.0, expr(x to 2.0)) - } - - @Test - fun testAdd() { - val expr = MstExtendedField { - binaryOperationFunction("+")( - bindSymbol(x), - bindSymbol(x), - ) - }.compileToExpression(DoubleField) - assertEquals(4.0, expr(x to 2.0)) - } - - @Test - fun testSine() { - val expr = MstExtendedField { unaryOperationFunction("sin")(bindSymbol(x)) }.compileToExpression(DoubleField) - assertEquals(0.0, expr(x to 0.0)) - } - - @Test - fun testSubtract() { - val expr = MstExtendedField { - binaryOperationFunction("-")(bindSymbol(x), - bindSymbol(x)) - }.compileToExpression(DoubleField) - assertEquals(0.0, expr(x to 2.0)) - } - - @Test - fun testDivide() { - val expr = MstExtendedField { - binaryOperationFunction("/")(bindSymbol(x), bindSymbol(x)) - }.compileToExpression(DoubleField) - assertEquals(1.0, expr(x to 2.0)) - } - - @Test - fun testPower() { - val expr = MstExtendedField { - binaryOperationFunction("pow")(bindSymbol(x), number(2)) - }.compileToExpression(DoubleField) - - assertEquals(4.0, expr(x to 2.0)) - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt deleted file mode 100644 index 89b98d720..000000000 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/asm/TestAsmVariables.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.asm - -import space.kscience.kmath.expressions.MstRing -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol -import space.kscience.kmath.operations.ByteRing -import space.kscience.kmath.operations.bindSymbol -import space.kscience.kmath.operations.invoke -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - -internal class TestAsmVariables { - @Test - fun testVariable() { - val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) - assertEquals(1.toByte(), expr(x to 1.toByte())) - } - - @Test - fun testUndefinedVariableFails() { - val expr = MstRing { bindSymbol(x) }.compileToExpression(ByteRing) - assertFailsWith { expr() } - } - - private companion object { - private val x by symbol - } -} diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt new file mode 100644 index 000000000..607c5fdd6 --- /dev/null +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -0,0 +1,25 @@ +/* + * 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.ast + +import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.asm.compile as asmCompile +import space.kscience.kmath.asm.compileToExpression as asmCompileToExpression + +private object AsmCompilerTestContext : CompilerTestContext { + override fun MST.compileToExpression(algebra: IntRing): Expression = asmCompileToExpression(algebra) + override fun MST.compile(algebra: IntRing, arguments: Map): Int = asmCompile(algebra, arguments) + override fun MST.compileToExpression(algebra: DoubleField): Expression = asmCompileToExpression(algebra) + + override fun MST.compile(algebra: DoubleField, arguments: Map): Double = + asmCompile(algebra, arguments) +} + +internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) = action(AsmCompilerTestContext) From 8898f908ef6cd6a3ce9458af13cc9abe160e8649 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Mon, 3 May 2021 18:45:18 +0300 Subject: [PATCH 279/393] statistic algebra --- .../tensors/api/StatisticTensorAlgebra.kt | 137 ++++++++++++++++++ .../algebras/DoubleStatisticTensorAlgebra.kt | 105 ++++++++++++++ 2 files changed, 242 insertions(+) create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt new file mode 100644 index 000000000..e3a2a1124 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt @@ -0,0 +1,137 @@ +/* + * 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.tensors.api + +import space.kscience.kmath.tensors.core.DoubleTensor + +/** + * Common algebra with statistics methods. Operates on [Tensor]. + * + * @param T the type of items closed under division in the tensors. + */ + +public interface StatisticTensorAlgebra: TensorAlgebra { + + /** + * Returns the minimum value of all elements in the input tensor. + * + * @return the minimum value of all elements in the input tensor. + */ + public fun Tensor.min(): Double + + /** + * Returns the minimum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the minimum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor + + /** + * Returns the maximum value of all elements in the input tensor. + * + * @return the maximum value of all elements in the input tensor. + */ + public fun Tensor.max(): Double + + /** + * Returns the maximum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the maximum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor + + /** + * Returns the sum of all elements in the input tensor. + * + * @return the sum of all elements in the input tensor. + */ + public fun Tensor.sum(): Double + + /** + * Returns the sum of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the sum of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor + + /** + * Returns the mean of all elements in the input tensor. + * + * @return the mean of all elements in the input tensor. + */ + public fun Tensor.mean(): Double + + /** + * Returns the mean of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the mean of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor + + /** + * Returns the standard deviation of all elements in the input tensor. + * + * @return the standard deviation of all elements in the input tensor. + */ + public fun Tensor.std(): Double + + /** + * Returns the standard deviation of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the standard deviation of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor + + /** + * Returns the variance of all elements in the input tensor. + * + * @return the variance of all elements in the input tensor. + */ + public fun Tensor.variance(): Double + + /** + * Returns the variance of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the variance of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt new file mode 100644 index 000000000..3914a0dfb --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt @@ -0,0 +1,105 @@ +/* + * 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.tensors.core.algebras + +import kotlin.math.sqrt + +import space.kscience.kmath.tensors.api.* +import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.max +import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.mean +import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.min +import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.sum +import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.variance + +public object DoubleStatisticTensorAlgebra : StatisticTensorAlgebra, DoubleTensorAlgebra() { + + private fun Tensor.fold(foldFunction: (DoubleArray) -> Double): Double { + return foldFunction(this.tensor.toDoubleArray()) + } + + private fun Tensor.foldDim( + foldFunction: (DoubleArray) -> Double, + dim: Int, + keepDim: Boolean + ): DoubleTensor { + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val resShape = if (keepDim) { + shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() + } else { + shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() + } + val resNumElements = resShape.reduce(Int::times) + val resTensor = DoubleTensor(resShape, DoubleArray(resNumElements) { 0.0 }, 0) + for (index in resTensor.linearStructure.indices()) { + val prefix = index.take(dim).toIntArray() + val suffix = index.takeLast(dimension - dim - 1).toIntArray() + resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i -> + this[prefix + intArrayOf(i) + suffix] + }) + } + + return resTensor + } + + override fun Tensor.min(): Double = this.fold { it.minOrNull()!! } + + override fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.minOrNull()!! }, dim, keepDim) + + override fun Tensor.max(): Double = this.fold { it.maxOrNull()!! } + + override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) + + override fun Tensor.sum(): Double = this.fold { it.sum() } + + override fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.sum() }, dim, keepDim) + + override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } + + override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + arr.sum() / shape[dim] + }, + dim, + keepDim + ) + + override fun Tensor.std(): Double = this.fold { arr -> + val mean = arr.sum() / tensor.numElements + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1)) + } + + override fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val mean = arr.sum() / shape[dim] + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) + }, + dim, + keepDim + ) + + override fun Tensor.variance(): Double = this.fold { arr -> + val mean = arr.sum() / tensor.numElements + arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1) + } + + override fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val mean = arr.sum() / shape[dim] + arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) + }, + dim, + keepDim + ) + +} \ No newline at end of file From 7f8914d8eacb6fb09469fa18b7328fa16bfc2208 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Mon, 3 May 2021 20:42:18 +0300 Subject: [PATCH 280/393] fixes --- .../kmath/tensors/api/StatisticTensorAlgebra.kt | 17 ++--------------- .../algebras/DoubleStatisticTensorAlgebra.kt | 7 +++---- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt index e3a2a1124..d0b17af97 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt @@ -9,16 +9,12 @@ import space.kscience.kmath.tensors.core.DoubleTensor /** * Common algebra with statistics methods. Operates on [Tensor]. - * - * @param T the type of items closed under division in the tensors. */ public interface StatisticTensorAlgebra: TensorAlgebra { /** * Returns the minimum value of all elements in the input tensor. - * - * @return the minimum value of all elements in the input tensor. */ public fun Tensor.min(): Double @@ -37,8 +33,6 @@ public interface StatisticTensorAlgebra: TensorAlgebra { /** * Returns the maximum value of all elements in the input tensor. - * - * @return the maximum value of all elements in the input tensor. */ public fun Tensor.max(): Double @@ -57,8 +51,6 @@ public interface StatisticTensorAlgebra: TensorAlgebra { /** * Returns the sum of all elements in the input tensor. - * - * @return the sum of all elements in the input tensor. */ public fun Tensor.sum(): Double @@ -77,8 +69,6 @@ public interface StatisticTensorAlgebra: TensorAlgebra { /** * Returns the mean of all elements in the input tensor. - * - * @return the mean of all elements in the input tensor. */ public fun Tensor.mean(): Double @@ -97,8 +87,6 @@ public interface StatisticTensorAlgebra: TensorAlgebra { /** * Returns the standard deviation of all elements in the input tensor. - * - * @return the standard deviation of all elements in the input tensor. */ public fun Tensor.std(): Double @@ -117,8 +105,6 @@ public interface StatisticTensorAlgebra: TensorAlgebra { /** * Returns the variance of all elements in the input tensor. - * - * @return the variance of all elements in the input tensor. */ public fun Tensor.variance(): Double @@ -134,4 +120,5 @@ public interface StatisticTensorAlgebra: TensorAlgebra { * @return the variance of each row of the input tensor in the given dimension [dim]. */ public fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor -} \ No newline at end of file + +} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt index 3914a0dfb..b455aff48 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt @@ -17,9 +17,8 @@ import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.v public object DoubleStatisticTensorAlgebra : StatisticTensorAlgebra, DoubleTensorAlgebra() { - private fun Tensor.fold(foldFunction: (DoubleArray) -> Double): Double { - return foldFunction(this.tensor.toDoubleArray()) - } + private fun Tensor.fold(foldFunction: (DoubleArray) -> Double): Double = + foldFunction(this.tensor.toDoubleArray()) private fun Tensor.foldDim( foldFunction: (DoubleArray) -> Double, @@ -102,4 +101,4 @@ public object DoubleStatisticTensorAlgebra : StatisticTensorAlgebra, Dou keepDim ) -} \ No newline at end of file +} From b59e48410f07ad203820b9c581b5e9997bff9784 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Mon, 3 May 2021 19:49:23 +0100 Subject: [PATCH 281/393] More basic functionality, tests to come --- .../tensors/api/AnalyticTensorAlgebra.kt | 95 +++++++++++++- .../tensors/api/StatisticTensorAlgebra.kt | 124 ------------------ .../kmath/tensors/api/TensorAlgebra.kt | 20 +++ .../algebras/DoubleAnalyticTensorAlgebra.kt | 54 ++++++++ .../algebras/DoubleStatisticTensorAlgebra.kt | 104 --------------- .../core/algebras/DoubleTensorAlgebra.kt | 36 ++++- 6 files changed, 202 insertions(+), 231 deletions(-) delete mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt delete mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index cd13e0752..f9b2df45c 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -5,14 +5,107 @@ package space.kscience.kmath.tensors.api + /** - * Element-wise analytic operations on [Tensor]. + * Analytic operations on [Tensor]. * * @param T the type of items closed under analytic functions in the tensors. */ public interface AnalyticTensorAlgebra : TensorPartialDivisionAlgebra { + + /** + * @return the minimum value of all elements in the input tensor. + */ + public fun Tensor.min(): T + + /** + * Returns the minimum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the minimum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.min(dim: Int, keepDim: Boolean): Tensor + + /** + * @return the maximum value of all elements in the input tensor. + */ + public fun Tensor.max(): T + + /** + * Returns the maximum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the maximum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.max(dim: Int, keepDim: Boolean): Tensor + + + /** + * @return the mean of all elements in the input tensor. + */ + public fun Tensor.mean(): T + + /** + * Returns the mean of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the mean of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.mean(dim: Int, keepDim: Boolean): Tensor + + /** + * @return the standard deviation of all elements in the input tensor. + */ + public fun Tensor.std(): T + + /** + * Returns the standard deviation of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the standard deviation of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.std(dim: Int, keepDim: Boolean): Tensor + + /** + * @return the variance of all elements in the input tensor. + */ + public fun Tensor.variance(): T + + /** + * Returns the variance of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the variance of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.variance(dim: Int, keepDim: Boolean): Tensor + //For information: https://pytorch.org/docs/stable/generated/torch.exp.html public fun Tensor.exp(): Tensor diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt deleted file mode 100644 index d0b17af97..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/StatisticTensorAlgebra.kt +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.tensors.api - -import space.kscience.kmath.tensors.core.DoubleTensor - -/** - * Common algebra with statistics methods. Operates on [Tensor]. - */ - -public interface StatisticTensorAlgebra: TensorAlgebra { - - /** - * Returns the minimum value of all elements in the input tensor. - */ - public fun Tensor.min(): Double - - /** - * Returns the minimum value of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the minimum value of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor - - /** - * Returns the maximum value of all elements in the input tensor. - */ - public fun Tensor.max(): Double - - /** - * Returns the maximum value of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the maximum value of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor - - /** - * Returns the sum of all elements in the input tensor. - */ - public fun Tensor.sum(): Double - - /** - * Returns the sum of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the sum of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor - - /** - * Returns the mean of all elements in the input tensor. - */ - public fun Tensor.mean(): Double - - /** - * Returns the mean of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the mean of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor - - /** - * Returns the standard deviation of all elements in the input tensor. - */ - public fun Tensor.std(): Double - - /** - * Returns the standard deviation of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the standard deviation of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor - - /** - * Returns the variance of all elements in the input tensor. - */ - public fun Tensor.variance(): Double - - /** - * Returns the variance of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the variance of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor - -} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index b9c707c0b..b99f79e9a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -251,4 +251,24 @@ public interface TensorAlgebra: Algebra> { dim2: Int = -1 ): Tensor + /** + * @return the sum of all elements in the input tensor. + */ + public fun Tensor.sum(): T + + /** + * Returns the sum of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the sum of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.sum(dim: Int, keepDim: Boolean): Tensor + + + } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 9aa6f093e..547018498 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -14,6 +14,60 @@ import kotlin.math.* public object DoubleAnalyticTensorAlgebra : AnalyticTensorAlgebra, DoubleTensorAlgebra() { + + override fun Tensor.min(): Double = this.fold { it.minOrNull()!! } + + override fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.minOrNull()!! }, dim, keepDim) + + override fun Tensor.max(): Double = this.fold { it.maxOrNull()!! } + + override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) + + + override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } + + override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + arr.sum() / shape[dim] + }, + dim, + keepDim + ) + + override fun Tensor.std(): Double = this.fold { arr -> + val mean = arr.sum() / tensor.numElements + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1)) + } + + override fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val mean = arr.sum() / shape[dim] + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) + }, + dim, + keepDim + ) + + override fun Tensor.variance(): Double = this.fold { arr -> + val mean = arr.sum() / tensor.numElements + arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1) + } + + override fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val mean = arr.sum() / shape[dim] + arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) + }, + dim, + keepDim + ) + override fun Tensor.exp(): DoubleTensor = tensor.map(::exp) override fun Tensor.log(): DoubleTensor = tensor.map(::ln) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt deleted file mode 100644 index b455aff48..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleStatisticTensorAlgebra.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.tensors.core.algebras - -import kotlin.math.sqrt - -import space.kscience.kmath.tensors.api.* -import space.kscience.kmath.tensors.core.* -import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.max -import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.mean -import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.min -import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.sum -import space.kscience.kmath.tensors.core.algebras.DoubleStatisticTensorAlgebra.variance - -public object DoubleStatisticTensorAlgebra : StatisticTensorAlgebra, DoubleTensorAlgebra() { - - private fun Tensor.fold(foldFunction: (DoubleArray) -> Double): Double = - foldFunction(this.tensor.toDoubleArray()) - - private fun Tensor.foldDim( - foldFunction: (DoubleArray) -> Double, - dim: Int, - keepDim: Boolean - ): DoubleTensor { - check(dim < dimension) { "Dimension $dim out of range $dimension" } - val resShape = if (keepDim) { - shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() - } else { - shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() - } - val resNumElements = resShape.reduce(Int::times) - val resTensor = DoubleTensor(resShape, DoubleArray(resNumElements) { 0.0 }, 0) - for (index in resTensor.linearStructure.indices()) { - val prefix = index.take(dim).toIntArray() - val suffix = index.takeLast(dimension - dim - 1).toIntArray() - resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i -> - this[prefix + intArrayOf(i) + suffix] - }) - } - - return resTensor - } - - override fun Tensor.min(): Double = this.fold { it.minOrNull()!! } - - override fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim({ x -> x.minOrNull()!! }, dim, keepDim) - - override fun Tensor.max(): Double = this.fold { it.maxOrNull()!! } - - override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) - - override fun Tensor.sum(): Double = this.fold { it.sum() } - - override fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim({ x -> x.sum() }, dim, keepDim) - - override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } - - override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim( - { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - arr.sum() / shape[dim] - }, - dim, - keepDim - ) - - override fun Tensor.std(): Double = this.fold { arr -> - val mean = arr.sum() / tensor.numElements - sqrt(arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1)) - } - - override fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( - { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - val mean = arr.sum() / shape[dim] - sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) - }, - dim, - keepDim - ) - - override fun Tensor.variance(): Double = this.fold { arr -> - val mean = arr.sum() / tensor.numElements - arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1) - } - - override fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( - { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - val mean = arr.sum() / shape[dim] - arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) - }, - dim, - keepDim - ) - -} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 4009f7b45..c0a6312a9 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -284,7 +284,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { val m1 = newThis.shape[newThis.shape.size - 1] val m2 = newOther.shape[newOther.shape.size - 2] val n = newOther.shape[newOther.shape.size - 1] - check (m1 == m2) { + check(m1 == m2) { throw RuntimeException("Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)") } @@ -403,7 +403,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun stack(tensors: List): DoubleTensor { val shape = tensors.firstOrNull()?.shape check(shape != null) { "Collection must have at least 1 element" } - check(tensors.all { it.shape contentEquals shape }) {"Stacking tensors must have same shapes"} + check(tensors.all { it.shape contentEquals shape }) { "Stacking tensors must have same shapes" } val resShape = intArrayOf(tensors.size) + shape val resBuffer = tensors.flatMap { it.tensor.mutableBuffer.array().drop(it.bufferStart).take(it.numElements) @@ -415,4 +415,36 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun Tensor.rowsByIndices(indices: IntArray): DoubleTensor { return stack(indices.map { this[it] }) } + + internal fun Tensor.fold(foldFunction: (DoubleArray) -> Double): Double = + foldFunction(tensor.toDoubleArray()) + + internal fun Tensor.foldDim( + foldFunction: (DoubleArray) -> Double, + dim: Int, + keepDim: Boolean + ): DoubleTensor { + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val resShape = if (keepDim) { + shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() + } else { + shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() + } + val resNumElements = resShape.reduce(Int::times) + val resTensor = DoubleTensor(resShape, DoubleArray(resNumElements) { 0.0 }, 0) + for (index in resTensor.linearStructure.indices()) { + val prefix = index.take(dim).toIntArray() + val suffix = index.takeLast(dimension - dim - 1).toIntArray() + resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i -> + tensor[prefix + intArrayOf(i) + suffix] + }) + } + + return resTensor + } + + override fun Tensor.sum(): Double = tensor.fold { it.sum() } + + override fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.sum() }, dim, keepDim) } From 591b40872954e1c91d50f3d9998b7cd8e0ea550b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 3 May 2021 04:14:19 +0700 Subject: [PATCH 282/393] MST rendering: support infix division, use arcsin instead sin^-1 form for inverse trigonometric functions --- README.md | 14 ++- kmath-ast/README.md | 89 +++++++++++++-- kmath-ast/docs/README-TEMPLATE.md | 103 ++++++++++++++++-- .../ast/rendering/LatexSyntaxRenderer.kt | 6 +- .../ast/rendering/MathMLSyntaxRenderer.kt | 15 ++- .../kmath/ast/rendering/MathRenderer.kt | 2 + .../kmath/ast/rendering/MathSyntax.kt | 32 +++--- .../kscience/kmath/ast/rendering/features.kt | 72 +++++++++--- .../kscience/kmath/ast/rendering/stages.kt | 76 ++++++++++++- .../kmath/ast/rendering/TestFeatures.kt | 18 +-- .../kmath/ast/rendering/TestStages.kt | 6 + kmath-for-real/README.md | 4 +- kmath-functions/README.md | 4 +- 13 files changed, 363 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 773eb6398..97ce164e1 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ KMath is a modular library. Different modules provide different features with di * ### [kmath-ast](kmath-ast) > > -> **Maturity**: PROTOTYPE +> **Maturity**: EXPERIMENTAL > > **Features:** > - [expression-language](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser @@ -154,9 +154,9 @@ performance calculations to code generation. > **Maturity**: PROTOTYPE > > **Features:** -> - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix. -> - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix. -> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix. +> - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : Point implementations. +> - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : Matrix implementation. +> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : LinearSpace implementations.
@@ -200,6 +200,12 @@ One can still use generic algebras though. > **Maturity**: PROTOTYPE
+* ### [kmath-jupyter](kmath-jupyter) +> +> +> **Maturity**: PROTOTYPE +
+ * ### [kmath-kotlingrad](kmath-kotlingrad) > > diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 4de165e72..26ee98ba5 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -1,6 +1,6 @@ # Module kmath-ast -Abstract syntax tree expression representation and related optimizations. +Performance and visualization extensions to MST API. - [expression-language](src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser - [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler @@ -39,12 +39,16 @@ dependencies { ### On JVM -`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds -a special implementation of `Expression` with implemented `invoke` function. +`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds a +special implementation of `Expression` with implemented `invoke` function. For example, the following builder: ```kotlin +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.* +import space.kscience.kmath.asm.* + MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` @@ -54,6 +58,7 @@ MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) package space.kscience.kmath.asm.generated; import java.util.Map; + import kotlin.jvm.functions.Function2; import space.kscience.kmath.asm.internal.MapIntrinsics; import space.kscience.kmath.expressions.Expression; @@ -63,7 +68,7 @@ public final class AsmCompiledExpression_45045_0 implements Expression { private final Object[] constants; public final Double invoke(Map arguments) { - return (Double)((Function2)this.constants[0]).invoke((Double)MapIntrinsics.getOrFail(arguments, "x"), 2); + return (Double) ((Function2) this.constants[0]).invoke((Double) MapIntrinsics.getOrFail(arguments, "x"), 2); } public AsmCompiledExpression_45045_0(Object[] constants) { @@ -75,8 +80,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression { #### Known issues -- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid - class loading overhead. +- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class + loading overhead. - This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders. ### On JS @@ -84,6 +89,10 @@ public final class AsmCompiledExpression_45045_0 implements Expression { A similar feature is also available on JS. ```kotlin +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.* +import space.kscience.kmath.estree.* + MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` @@ -91,13 +100,16 @@ The code above returns expression implemented with such a JS function: ```js var executable = function (constants, arguments) { - return constants[1](constants[0](arguments, "x"), 2); + return constants[1](constants[0](arguments, "x"), 2); }; ``` -JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported. +JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. +Currently, only expressions inside `DoubleField` and `IntRing` are supported. ```kotlin +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.* import space.kscience.kmath.wasm.* MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) @@ -128,7 +140,9 @@ Example usage: ```kotlin import space.kscience.kmath.ast.* import space.kscience.kmath.ast.rendering.* +import space.kscience.kmath.misc.* +@OptIn(UnstableKMathAPI::class) public fun main() { val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath() val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst) @@ -144,13 +158,68 @@ public fun main() { Result LaTeX: -![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D) +![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{-12}) Result MathML (embedding MathML is not allowed by GitHub Markdown): +
+ ```html -ex-sin-12x2×1010+x3-12 + + + exp + + + + x + + + - + + + + + arcsin + + + 2 + + x + + + + 2 + × + + + 10 + + + 10 + + + + + + + x + + + 3 + + + + + + + - + 12 + + + + ``` +
+ It is also possible to create custom algorithms of render, and even add support of other markup languages (see API reference). diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index 1ecf477ef..80ea31642 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -1,6 +1,6 @@ # Module kmath-ast -Abstract syntax tree expression representation and related optimizations. +Performance and visualization extensions to MST API. ${features} @@ -10,12 +10,16 @@ ${artifact} ### On JVM -`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds -a special implementation of `Expression` with implemented `invoke` function. +`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds a +special implementation of `Expression` with implemented `invoke` function. For example, the following builder: ```kotlin +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.* +import space.kscience.kmath.asm.* + MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` @@ -25,6 +29,7 @@ MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) package space.kscience.kmath.asm.generated; import java.util.Map; + import kotlin.jvm.functions.Function2; import space.kscience.kmath.asm.internal.MapIntrinsics; import space.kscience.kmath.expressions.Expression; @@ -34,7 +39,7 @@ public final class AsmCompiledExpression_45045_0 implements Expression { private final Object[] constants; public final Double invoke(Map arguments) { - return (Double)((Function2)this.constants[0]).invoke((Double)MapIntrinsics.getOrFail(arguments, "x"), 2); + return (Double) ((Function2) this.constants[0]).invoke((Double) MapIntrinsics.getOrFail(arguments, "x"), 2); } public AsmCompiledExpression_45045_0(Object[] constants) { @@ -46,8 +51,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression { #### Known issues -- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid - class loading overhead. +- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class + loading overhead. - This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders. ### On JS @@ -55,6 +60,10 @@ public final class AsmCompiledExpression_45045_0 implements Expression { A similar feature is also available on JS. ```kotlin +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.* +import space.kscience.kmath.estree.* + MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) ``` @@ -62,13 +71,16 @@ The code above returns expression implemented with such a JS function: ```js var executable = function (constants, arguments) { - return constants[1](constants[0](arguments, "x"), 2); + return constants[1](constants[0](arguments, "x"), 2); }; ``` -JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. Currently, only expressions inside `DoubleField` and `IntRing` are supported. +JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation. +Currently, only expressions inside `DoubleField` and `IntRing` are supported. ```kotlin +import space.kscience.kmath.expressions.* +import space.kscience.kmath.operations.* import space.kscience.kmath.wasm.* MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) @@ -99,9 +111,11 @@ Example usage: ```kotlin import space.kscience.kmath.ast.* import space.kscience.kmath.ast.rendering.* +import space.kscience.kmath.misc.* +@OptIn(UnstableKMathAPI::class) public fun main() { - val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath() + val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(12)+x^(2/3)".parseMath() val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst) val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax) println("LaTeX:") @@ -115,13 +129,78 @@ public fun main() { Result LaTeX: -![](http://chart.googleapis.com/chart?cht=tx&chl=e%5E%7B%5Csqrt%7Bx%7D%7D-%5Cfrac%7B%5Cfrac%7B%5Coperatorname%7Bsin%7D%5E%7B-1%7D%5C,%5Cleft(2%5C,x%5Cright)%7D%7B2%5Ctimes10%5E%7B10%7D%2Bx%5E%7B3%7D%7D%7D%7B-12%7D) +![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3}) -Result MathML (embedding MathML is not allowed by GitHub Markdown): +Result MathML (can be used with MathJax or other renderers): + +
```html -ex-sin-12x2×1010+x3-12 + + + exp + + + + x + + + - + + + + + arcsin + + + 2 + + x + + + + 2 + × + + + 10 + + + 10 + + + + + + + x + + + 3 + + + + + + + 12 + + + + + + + x + + + 2 + / + 3 + + + + ``` +
+ It is also possible to create custom algorithms of render, and even add support of other markup languages (see API reference). diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt index 5909f1f9d..01717b0f9 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -118,7 +118,11 @@ public object LatexSyntaxRenderer : SyntaxRenderer { render(node.right) } - is FractionSyntax -> { + is FractionSyntax -> if (node.infix) { + render(node.left) + append('/') + render(node.right) + } else { append("\\frac{") render(node.left) append("}{") diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index 5b44e660d..cda8e2322 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -133,14 +133,13 @@ public object MathMLSyntaxRenderer : SyntaxRenderer { render(node.right) } - is FractionSyntax -> tag("mfrac") { - tag("mrow") { - render(node.left) - } - - tag("mrow") { - render(node.right) - } + is FractionSyntax -> if (node.infix) { + render(node.left) + tag("mo") { append('/') } + render(node.right) + } else tag("mfrac") { + tag("mrow") { render(node.left) } + tag("mrow") { render(node.right) } } is RadicalWithIndexSyntax -> tag("mroot") { diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index 6b22ac519..c33f95483 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -89,6 +89,7 @@ public open class FeaturedMathRendererWithPostProcess( SquareRoot.Default, Exponent.Default, InverseTrigonometricOperations.Default, + InverseHyperbolicOperations.Default, // Fallback option for unknown operations - printing them as operator BinaryOperator.Default, @@ -105,6 +106,7 @@ public open class FeaturedMathRendererWithPostProcess( ), listOf( BetterExponent, + BetterFraction, SimplifyParentheses.Default, BetterMultiplication, ), diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt index 3c023e342..a71985fbc 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -102,7 +102,7 @@ public data class SymbolSyntax(public var string: String) : TerminalSyntax() public data class OperatorNameSyntax(public var name: String) : TerminalSyntax() /** - * Represents a usage of special symbols. + * Represents a usage of special symbols (e.g., *∞*). * * @property kind The kind of symbol. * @author Iaroslav Postovalov @@ -143,7 +143,7 @@ public data class OperandSyntax( } /** - * Represents unary, prefix operator syntax (like f x). + * Represents unary, prefix operator syntax (like *f(x)*). * * @property prefix The prefix. * @author Iaroslav Postovalov @@ -160,7 +160,7 @@ public data class UnaryOperatorSyntax( } /** - * Represents prefix, unary plus operator. + * Represents prefix, unary plus operator (*+x*). * * @author Iaroslav Postovalov */ @@ -175,7 +175,7 @@ public data class UnaryPlusSyntax( } /** - * Represents prefix, unary minus operator. + * Represents prefix, unary minus operator (*-x*). * * @author Iaroslav Postovalov */ @@ -190,7 +190,7 @@ public data class UnaryMinusSyntax( } /** - * Represents radical with a node inside it. + * Represents radical with a node inside it (*√x*). * * @property operand The radicand. * @author Iaroslav Postovalov @@ -225,7 +225,7 @@ public data class ExponentSyntax( } /** - * Represents a syntax node with superscript (usually, for exponentiation). + * Represents a syntax node with superscript (*x2*). * * @property left The node. * @property right The superscript. @@ -244,7 +244,7 @@ public data class SuperscriptSyntax( } /** - * Represents a syntax node with subscript. + * Represents a syntax node with subscript (*xi*). * * @property left The node. * @property right The subscript. @@ -263,7 +263,7 @@ public data class SubscriptSyntax( } /** - * Represents binary, prefix operator syntax (like f(a, b)). + * Represents binary, prefix operator syntax (like *f(a, b)*). * * @property prefix The prefix. * @author Iaroslav Postovalov @@ -282,7 +282,7 @@ public data class BinaryOperatorSyntax( } /** - * Represents binary, infix addition. + * Represents binary, infix addition (*42 + 42*). * * @param left The augend. * @param right The addend. @@ -301,7 +301,7 @@ public data class BinaryPlusSyntax( } /** - * Represents binary, infix subtraction. + * Represents binary, infix subtraction (*42 - 42*). * * @param left The minuend. * @param right The subtrahend. @@ -324,13 +324,15 @@ public data class BinaryMinusSyntax( * * @property left The numerator. * @property right The denominator. + * @property infix Whether infix (*1 / 2*) or normal (*½*) fraction should be made. * @author Iaroslav Postovalov */ @UnstableKMathAPI public data class FractionSyntax( public override val operation: String, - public override val left: MathSyntax, - public override val right: MathSyntax, + public override val left: OperandSyntax, + public override val right: OperandSyntax, + public var infix: Boolean, ) : BinarySyntax() { init { left.parent = this @@ -339,7 +341,7 @@ public data class FractionSyntax( } /** - * Represents radical syntax with index. + * Represents radical syntax with index (*3√x*). * * @property left The index. * @property right The radicand. @@ -358,11 +360,11 @@ public data class RadicalWithIndexSyntax( } /** - * Represents binary, infix multiplication in the form of coefficient (2 x) or with operator (x×2). + * Represents binary, infix multiplication in the form of coefficient (*2 x*) or with operator (*x × 2*). * * @property left The multiplicand. * @property right The multiplier. - * @property times whether the times (×) symbol should be used. + * @property times Whether the times (×) symbol should be used. * @author Iaroslav Postovalov */ @UnstableKMathAPI diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index c1b513345..ac716f9ff 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -54,6 +54,7 @@ else * *('-'? (DIGIT+ ('.' DIGIT+)? ('E' '-'? DIGIT+)? | 'Infinity')) | 'NaN'*. * * @property types The suitable types. + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class PrettyPrintFloats(public val types: Set>) : RenderFeature { @@ -113,6 +114,7 @@ public class PrettyPrintFloats(public val types: Set>) : Rend * Special printing for numeric types which are printed in form of *'-'? DIGIT+*. * * @property types The suitable types. + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class PrettyPrintIntegers(public val types: Set>) : RenderFeature { @@ -135,6 +137,7 @@ public class PrettyPrintIntegers(public val types: Set>) : Re * Special printing for symbols meaning Pi. * * @property symbols The allowed symbols. + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class PrettyPrintPi(public val symbols: Set) : RenderFeature { @@ -157,6 +160,7 @@ public class PrettyPrintPi(public val symbols: Set) : RenderFeature { * not [MST.Unary]. * * @param operations the allowed operations. If `null`, any operation is accepted. + * @author Iaroslav Postovalov */ @UnstableKMathAPI public abstract class Unary(public val operations: Collection?) : RenderFeature { @@ -177,6 +181,7 @@ public abstract class Unary(public val operations: Collection?) : Render * not [MST.Binary]. * * @property operations the allowed operations. If `null`, any operation is accepted. + * @author Iaroslav Postovalov */ @UnstableKMathAPI public abstract class Binary(public val operations: Collection?) : RenderFeature { @@ -193,6 +198,8 @@ public abstract class Binary(public val operations: Collection?) : Rende /** * Handles binary nodes by producing [BinaryPlusSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class BinaryPlus(operations: Collection?) : Binary(operations) { @@ -213,6 +220,8 @@ public class BinaryPlus(operations: Collection?) : Binary(operations) { /** * Handles binary nodes by producing [BinaryMinusSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class BinaryMinus(operations: Collection?) : Binary(operations) { @@ -233,6 +242,8 @@ public class BinaryMinus(operations: Collection?) : Binary(operations) { /** * Handles unary nodes by producing [UnaryPlusSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class UnaryPlus(operations: Collection?) : Unary(operations) { @@ -251,6 +262,8 @@ public class UnaryPlus(operations: Collection?) : Unary(operations) { /** * Handles binary nodes by producing [UnaryMinusSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class UnaryMinus(operations: Collection?) : Unary(operations) { @@ -269,13 +282,16 @@ public class UnaryMinus(operations: Collection?) : Unary(operations) { /** * Handles binary nodes by producing [FractionSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class Fraction(operations: Collection?) : Binary(operations) { public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = FractionSyntax( operation = node.operation, - left = parent.render(node.left), - right = parent.render(node.right), + left = OperandSyntax(operand = parent.render(node.left), parentheses = true), + right = OperandSyntax(operand = parent.render(node.right), parentheses = true), + infix = true, ) public companion object { @@ -288,6 +304,8 @@ public class Fraction(operations: Collection?) : Binary(operations) { /** * Handles binary nodes by producing [BinaryOperatorSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class BinaryOperator(operations: Collection?) : Binary(operations) { @@ -309,6 +327,8 @@ public class BinaryOperator(operations: Collection?) : Binary(operations /** * Handles unary nodes by producing [UnaryOperatorSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class UnaryOperator(operations: Collection?) : Unary(operations) { @@ -329,6 +349,8 @@ public class UnaryOperator(operations: Collection?) : Unary(operations) /** * Handles binary nodes by producing [SuperscriptSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class Power(operations: Collection?) : Binary(operations) { @@ -365,6 +387,8 @@ public class SquareRoot(operations: Collection?) : Unary(operations) { /** * Handles unary nodes by producing [ExponentSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class Exponent(operations: Collection?) : Unary(operations) { @@ -384,6 +408,8 @@ public class Exponent(operations: Collection?) : Unary(operations) { /** * Handles binary nodes by producing [MultiplicationSyntax]. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class Multiplication(operations: Collection?) : Binary(operations) { @@ -404,36 +430,52 @@ public class Multiplication(operations: Collection?) : Binary(operations } /** - * Handles binary nodes by producing inverse [UnaryOperatorSyntax] (like *sin-1*) with removing the `a` - * prefix of operation ID. + * Handles binary nodes by producing inverse [UnaryOperatorSyntax] with *arc* prefix instead of *a*. + * + * @author Iaroslav Postovalov */ @UnstableKMathAPI public class InverseTrigonometricOperations(operations: Collection?) : Unary(operations) { public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = UnaryOperatorSyntax( operation = node.operation, - prefix = SuperscriptSyntax( - operation = PowerOperations.POW_OPERATION, - left = OperatorNameSyntax(name = node.operation.removePrefix("a")), - right = UnaryMinusSyntax( - operation = GroupOperations.MINUS_OPERATION, - operand = OperandSyntax(operand = NumberSyntax(string = "1"), parentheses = true), - ), - ), + prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "arc")), operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), ) public companion object { /** * The default instance configured with [TrigonometricOperations.ACOS_OPERATION], - * [TrigonometricOperations.ASIN_OPERATION], [TrigonometricOperations.ATAN_OPERATION], - * [ExponentialOperations.ACOSH_OPERATION], [ExponentialOperations.ASINH_OPERATION], and - * [ExponentialOperations.ATANH_OPERATION]. + * [TrigonometricOperations.ASIN_OPERATION], [TrigonometricOperations.ATAN_OPERATION]. */ public val Default: InverseTrigonometricOperations = InverseTrigonometricOperations(setOf( TrigonometricOperations.ACOS_OPERATION, TrigonometricOperations.ASIN_OPERATION, TrigonometricOperations.ATAN_OPERATION, + )) + } +} + +/** + * Handles binary nodes by producing inverse [UnaryOperatorSyntax] with *ar* prefix instead of *a*. + * + * @author Iaroslav Postovalov + */ +@UnstableKMathAPI +public class InverseHyperbolicOperations(operations: Collection?) : Unary(operations) { + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = + UnaryOperatorSyntax( + operation = node.operation, + prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "ar")), + operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), + ) + + public companion object { + /** + * The default instance configured with [ExponentialOperations.ACOSH_OPERATION], + * [ExponentialOperations.ASINH_OPERATION], and [ExponentialOperations.ATANH_OPERATION]. + */ + public val Default: InverseHyperbolicOperations = InverseHyperbolicOperations(setOf( ExponentialOperations.ACOSH_OPERATION, ExponentialOperations.ASINH_OPERATION, ExponentialOperations.ATANH_OPERATION, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt index 7eb75b9ff..1f31af853 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt @@ -83,6 +83,75 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro } } +/** + * Chooses [FractionSyntax.infix] depending on the context. + * + * @author Iaroslav Postovalov + */ +@UnstableKMathAPI +public object BetterFraction : FeaturedMathRendererWithPostProcess.PostProcessStage { + private fun perform0(node: MathSyntax, infix: Boolean = false): Unit = when (node) { + is NumberSyntax -> Unit + is SymbolSyntax -> Unit + is OperatorNameSyntax -> Unit + is SpecialSymbolSyntax -> Unit + is OperandSyntax -> perform0(node.operand, infix) + + is UnaryOperatorSyntax -> { + perform0(node.prefix, infix) + perform0(node.operand, infix) + } + + is UnaryPlusSyntax -> perform0(node.operand, infix) + is UnaryMinusSyntax -> perform0(node.operand, infix) + is RadicalSyntax -> perform0(node.operand, infix) + is ExponentSyntax -> perform0(node.operand, infix) + + is SuperscriptSyntax -> { + perform0(node.left, true) + perform0(node.right, true) + } + + is SubscriptSyntax -> { + perform0(node.left, true) + perform0(node.right, true) + } + + is BinaryOperatorSyntax -> { + perform0(node.prefix, infix) + perform0(node.left, infix) + perform0(node.right, infix) + } + + is BinaryPlusSyntax -> { + perform0(node.left, infix) + perform0(node.right, infix) + } + + is BinaryMinusSyntax -> { + perform0(node.left, infix) + perform0(node.right, infix) + } + + is FractionSyntax -> { + node.infix = infix + perform0(node.left, infix) + perform0(node.right, infix) + } + + is RadicalWithIndexSyntax -> { + perform0(node.left, true) + perform0(node.right, true) + } + + is MultiplicationSyntax -> { + perform0(node.left, infix) + perform0(node.right, infix) + } + } + + public override fun perform(node: MathSyntax): Unit = perform0(node) +} /** * Applies [ExponentSyntax.useOperatorForm] to [ExponentSyntax] when the operand contains a fraction, a @@ -102,7 +171,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt is UnaryOperatorSyntax -> perform0(node.prefix) || perform0(node.operand) is UnaryPlusSyntax -> perform0(node.operand) is UnaryMinusSyntax -> perform0(node.operand) - is RadicalSyntax -> perform0(node.operand) + is RadicalSyntax -> true is ExponentSyntax -> { val r = perform0(node.operand) @@ -116,7 +185,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt is BinaryPlusSyntax -> perform0(node.left) || perform0(node.right) is BinaryMinusSyntax -> perform0(node.left) || perform0(node.right) is FractionSyntax -> true - is RadicalWithIndexSyntax -> perform0(node.left) || perform0(node.right) + is RadicalWithIndexSyntax -> true is MultiplicationSyntax -> perform0(node.left) || perform0(node.right) } } @@ -163,8 +232,11 @@ public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> val isInsideExpOperator = node.parent is ExponentSyntax && (node.parent as ExponentSyntax).useOperatorForm + val isOnOrUnderNormalFraction = node.parent is FractionSyntax && !((node.parent as FractionSyntax).infix) + node.parentheses = !isRightOfSuperscript && (needParenthesesByPrecedence || node.parent is UnaryOperatorSyntax || isInsideExpOperator) + && !isOnOrUnderNormalFraction perform(node.operand) } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt index 1ab20ed85..a40c785b9 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt @@ -99,13 +99,17 @@ internal class TestFeatures { fun multiplication() = testLatex("x*1", "x\\times1") @Test - fun inverseTrigonometry() { - testLatex("asin(x)", "\\operatorname{sin}^{-1}\\,\\left(x\\right)") - testLatex("asinh(x)", "\\operatorname{sinh}^{-1}\\,\\left(x\\right)") - testLatex("acos(x)", "\\operatorname{cos}^{-1}\\,\\left(x\\right)") - testLatex("acosh(x)", "\\operatorname{cosh}^{-1}\\,\\left(x\\right)") - testLatex("atan(x)", "\\operatorname{tan}^{-1}\\,\\left(x\\right)") - testLatex("atanh(x)", "\\operatorname{tanh}^{-1}\\,\\left(x\\right)") + fun inverseTrigonometric() { + testLatex("asin(x)", "\\operatorname{arcsin}\\,\\left(x\\right)") + testLatex("acos(x)", "\\operatorname{arccos}\\,\\left(x\\right)") + testLatex("atan(x)", "\\operatorname{arctan}\\,\\left(x\\right)") + } + + @Test + fun inverseHyperbolic() { + testLatex("asinh(x)", "\\operatorname{arsinh}\\,\\left(x\\right)") + testLatex("acosh(x)", "\\operatorname{arcosh}\\,\\left(x\\right)") + testLatex("atanh(x)", "\\operatorname{artanh}\\,\\left(x\\right)") } // @Test diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt index 599e43eb2..09ec127c7 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt @@ -37,4 +37,10 @@ internal class TestStages { testLatex("exp(x/2)", "\\operatorname{exp}\\,\\left(\\frac{x}{2}\\right)") testLatex("exp(x^2)", "\\operatorname{exp}\\,\\left(x^{2}\\right)") } + + @Test + fun fraction() { + testLatex("x/y", "\\frac{x}{y}") + testLatex("x^(x/y)", "x^{x/y}") + } } diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 46bf657c3..a77f9d98b 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -15,7 +15,7 @@ The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-d ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -26,7 +26,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + mavenCentral() } dependencies { diff --git a/kmath-functions/README.md b/kmath-functions/README.md index c7c30f1a1..2090ede3e 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -17,7 +17,7 @@ The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0- ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { @@ -28,7 +28,7 @@ dependencies { ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap + mavenCentral() } dependencies { From d0281871fac1f59f4218ea1e4440f1991e742bb1 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Wed, 5 May 2021 14:27:01 +0300 Subject: [PATCH 283/393] analytic tests and examples --- .../kmath/tensors/DataSetNormalization.kt | 46 ++++++ .../tensors/api/AnalyticTensorAlgebra.kt | 3 +- .../algebras/DoubleAnalyticTensorAlgebra.kt | 3 +- .../core/TestDoubleAnalyticTensorAlgebra.kt | 152 ++++++++++++++++-- 4 files changed, 186 insertions(+), 18 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt new file mode 100644 index 000000000..4d53d940b --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt @@ -0,0 +1,46 @@ +/* + * 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.tensors + +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra + +// Dataset normalization + +fun main() { + + // work in context with analytic methods + DoubleAnalyticTensorAlgebra { + // take dataset of 5-element vectors from normal distribution + val dataset = randomNormal(intArrayOf(100, 5)) * 1.5 // all elements from N(0, 1.5) + BroadcastDoubleTensorAlgebra { + dataset += fromArray( + intArrayOf(5), + doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means + ) + } + + // find out mean and standard deviation of each column + val mean = dataset.mean(0, false) + val std = dataset.std(0, false) + + println("Mean:\n$mean") + println("Standard deviation:\n$std") + + // also we can calculate other statistic as minimum and maximum of rows + println("Minimum:\n${dataset.min(0, false)}") + println("Maximum:\n${dataset.max(0, false)}") + + // now we can scale dataset with mean normalization + val datasetScaled = BroadcastDoubleTensorAlgebra { (dataset - mean) / std } + + // find out mean and std of scaled dataset + + println("Mean of scaled:\n${datasetScaled.mean(0, false)}") + println("Mean of scaled:\n${datasetScaled.std(0, false)}") + } +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index f9b2df45c..7784bfa45 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -51,7 +51,6 @@ public interface AnalyticTensorAlgebra : */ public fun Tensor.max(dim: Int, keepDim: Boolean): Tensor - /** * @return the mean of all elements in the input tensor. */ @@ -110,7 +109,7 @@ public interface AnalyticTensorAlgebra : public fun Tensor.exp(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.log.html - public fun Tensor.log(): Tensor + public fun Tensor.ln(): Tensor //For information: https://pytorch.org/docs/stable/generated/torch.sqrt.html public fun Tensor.sqrt(): Tensor diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 547018498..5580f845f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -25,7 +25,6 @@ public object DoubleAnalyticTensorAlgebra : override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) - override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = @@ -70,7 +69,7 @@ public object DoubleAnalyticTensorAlgebra : override fun Tensor.exp(): DoubleTensor = tensor.map(::exp) - override fun Tensor.log(): DoubleTensor = tensor.map(::ln) + override fun Tensor.ln(): DoubleTensor = tensor.map(::ln) override fun Tensor.sqrt(): DoubleTensor = tensor.map(::sqrt) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 835b8a08a..bebd65dc5 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -2,35 +2,159 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra -import kotlin.math.abs -import kotlin.math.exp +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.tan +import kotlin.math.* import kotlin.test.Test import kotlin.test.assertTrue internal class TestDoubleAnalyticTensorAlgebra { val shape = intArrayOf(2, 1, 3, 2) - val buffer = doubleArrayOf(27.1, 20.0, 19.84, 23.123, 0.0, 1.0, 3.23, 133.7, 25.3, 100.3, 11.0, 12.012) + val buffer = doubleArrayOf( + 27.1, 20.0, 19.84, + 23.123, 3.0, 2.0, + + 3.23, 133.7, 25.3, + 100.3, 11.0, 12.012 + ) val tensor = DoubleTensor(shape, buffer) fun DoubleArray.fmap(transform: (Double) -> Double): DoubleArray { return this.map(transform).toDoubleArray() } - fun DoubleArray.epsEqual(other: DoubleArray, eps: Double = 1e-5): Boolean { - for ((elem1, elem2) in this.asSequence().zip(other.asSequence())) { - if (abs(elem1 - elem2) > eps) { - return false - } - } - return true + fun expectedTensor(transform: (Double) -> Double): DoubleTensor { + return DoubleTensor(shape, buffer.fmap(transform)) } @Test fun testExp() = DoubleAnalyticTensorAlgebra { - tensor.exp().let { - assertTrue { shape contentEquals it.shape } - assertTrue { buffer.fmap(::exp).epsEqual(it.mutableBuffer.array())} - } + assertTrue { tensor.exp() eq expectedTensor(::exp) } } + + @Test + fun testLog() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.ln() eq expectedTensor(::ln) } + } + + @Test + fun testSqrt() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.sqrt() eq expectedTensor(::sqrt) } + } + + @Test + fun testCos() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.cos() eq expectedTensor(::cos) } + } + + + @Test + fun testCosh() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.cosh() eq expectedTensor(::cosh) } + } + + @Test + fun testAcosh() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.acosh() eq expectedTensor(::acosh) } + } + + @Test + fun testSin() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.sin() eq expectedTensor(::sin) } + } + + @Test + fun testSinh() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.sinh() eq expectedTensor(::sinh) } + } + + @Test + fun testAsinh() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.asinh() eq expectedTensor(::asinh) } + } + + @Test + fun testTan() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.tan() eq expectedTensor(::tan) } + } + + @Test + fun testAtan() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.atan() eq expectedTensor(::atan) } + } + + @Test + fun testTanh() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.tanh() eq expectedTensor(::tanh) } + } + + @Test + fun testCeil() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.ceil() eq expectedTensor(::ceil) } + } + + @Test + fun testFloor() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor.floor() eq expectedTensor(::floor) } + } + + val shape2 = intArrayOf(2, 2) + val buffer2 = doubleArrayOf( + 1.0, 2.0, + -3.0, 4.0 + ) + val tensor2 = DoubleTensor(shape2, buffer2) + + @Test + fun testMin() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor2.min() == -3.0 } + assertTrue { tensor2.min(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(-3.0, 2.0) + )} + assertTrue { tensor2.min(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(1.0, -3.0) + )} + } + + @Test + fun testMax() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor2.max() == 4.0 } + assertTrue { tensor2.max(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(1.0, 4.0) + )} + assertTrue { tensor2.max(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(2.0, 4.0) + )} + } + + @Test + fun testSum() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor2.sum() == 4.0 } + assertTrue { tensor2.sum(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(-2.0, 6.0) + )} + assertTrue { tensor2.sum(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(3.0, 1.0) + )} + } + + @Test + fun testMean() = DoubleAnalyticTensorAlgebra { + assertTrue { tensor2.mean() == 1.0 } + assertTrue { tensor2.mean(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(-1.0, 3.0) + )} + assertTrue { tensor2.mean(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(1.5, 0.5) + )} + } + } \ No newline at end of file From 218b81a242b79baba4cb8db82887e4fa90556b05 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 5 May 2021 16:11:46 +0100 Subject: [PATCH 284/393] Min max refactor --- .../tensors/api/AnalyticTensorAlgebra.kt | 37 ------------------- .../kmath/tensors/api/TensorAlgebra.kt | 35 ++++++++++++++++++ .../algebras/DoubleAnalyticTensorAlgebra.kt | 10 ----- .../core/algebras/DoubleTensorAlgebra.kt | 14 +++++++ .../core/TestDoubleAnalyticTensorAlgebra.kt | 8 ++-- 5 files changed, 53 insertions(+), 51 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 7784bfa45..aa5678b31 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -14,43 +14,6 @@ package space.kscience.kmath.tensors.api public interface AnalyticTensorAlgebra : TensorPartialDivisionAlgebra { - - /** - * @return the minimum value of all elements in the input tensor. - */ - public fun Tensor.min(): T - - /** - * Returns the minimum value of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the minimum value of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.min(dim: Int, keepDim: Boolean): Tensor - - /** - * @return the maximum value of all elements in the input tensor. - */ - public fun Tensor.max(): T - - /** - * Returns the maximum value of each row of the input tensor in the given dimension [dim]. - * - * If [keepDim] is true, the output tensor is of the same size as - * input except in the dimension [dim] where it is of size 1. - * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. - * - * @param dim the dimension to reduce. - * @param keepDim whether the output tensor has [dim] retained or not. - * @return the maximum value of each row of the input tensor in the given dimension [dim]. - */ - public fun Tensor.max(dim: Int, keepDim: Boolean): Tensor - /** * @return the mean of all elements in the input tensor. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index b99f79e9a..b0a0f9618 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -269,6 +269,41 @@ public interface TensorAlgebra: Algebra> { */ public fun Tensor.sum(dim: Int, keepDim: Boolean): Tensor + /** + * @return the minimum value of all elements in the input tensor. + */ + public fun Tensor.min(): T + + /** + * Returns the minimum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the minimum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.min(dim: Int, keepDim: Boolean): Tensor + + /** + * @return the maximum value of all elements in the input tensor. + */ + public fun Tensor.max(): T + + /** + * Returns the maximum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the maximum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.max(dim: Int, keepDim: Boolean): Tensor } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 5580f845f..4a1f360e3 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -15,16 +15,6 @@ public object DoubleAnalyticTensorAlgebra : AnalyticTensorAlgebra, DoubleTensorAlgebra() { - override fun Tensor.min(): Double = this.fold { it.minOrNull()!! } - - override fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim({ x -> x.minOrNull()!! }, dim, keepDim) - - override fun Tensor.max(): Double = this.fold { it.maxOrNull()!! } - - override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) - override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index c0a6312a9..d220bdd9a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -9,6 +9,8 @@ import space.kscience.kmath.nd.as2D import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.fold +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.foldDim import space.kscience.kmath.tensors.core.broadcastOuterTensors import space.kscience.kmath.tensors.core.checkBufferShapeConsistency import space.kscience.kmath.tensors.core.checkEmptyDoubleBuffer @@ -447,4 +449,16 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor = foldDim({ x -> x.sum() }, dim, keepDim) + + + override fun Tensor.min(): Double = this.fold { it.minOrNull()!! } + + override fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.minOrNull()!! }, dim, keepDim) + + override fun Tensor.max(): Double = this.fold { it.maxOrNull()!! } + + override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) + } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index bebd65dc5..3ea19da26 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -2,7 +2,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.tan +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.math.* import kotlin.test.Test import kotlin.test.assertTrue @@ -106,7 +106,7 @@ internal class TestDoubleAnalyticTensorAlgebra { val tensor2 = DoubleTensor(shape2, buffer2) @Test - fun testMin() = DoubleAnalyticTensorAlgebra { + fun testMin() = DoubleTensorAlgebra { assertTrue { tensor2.min() == -3.0 } assertTrue { tensor2.min(0, true) eq fromArray( intArrayOf(1, 2), @@ -119,7 +119,7 @@ internal class TestDoubleAnalyticTensorAlgebra { } @Test - fun testMax() = DoubleAnalyticTensorAlgebra { + fun testMax() = DoubleTensorAlgebra { assertTrue { tensor2.max() == 4.0 } assertTrue { tensor2.max(0, true) eq fromArray( intArrayOf(1, 2), @@ -132,7 +132,7 @@ internal class TestDoubleAnalyticTensorAlgebra { } @Test - fun testSum() = DoubleAnalyticTensorAlgebra { + fun testSum() = DoubleTensorAlgebra { assertTrue { tensor2.sum() == 4.0 } assertTrue { tensor2.sum(0, true) eq fromArray( intArrayOf(1, 2), From 431db00f1ac9da54b65d00a09fa6f7b33c150942 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 5 May 2021 16:35:26 +0100 Subject: [PATCH 285/393] refactor tests --- .../kmath/tensors/core/TestBroadcasting.kt | 12 ++++---- .../kmath/tensors/core/TestDoubleTensor.kt | 8 ++--- .../tensors/core/TestDoubleTensorAlgebra.kt | 30 ++++++------------- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 1564b85c9..6e3b4df60 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -9,7 +9,7 @@ import kotlin.test.assertTrue internal class TestBroadcasting { @Test - fun broadcastShapes() = DoubleTensorAlgebra { + fun testBroadcastShapes() = DoubleTensorAlgebra { assertTrue( broadcastShapes( intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1) @@ -24,7 +24,7 @@ internal class TestBroadcasting { } @Test - fun broadcastTo() = DoubleTensorAlgebra { + fun testBroadcastTo() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) @@ -34,7 +34,7 @@ internal class TestBroadcasting { } @Test - fun broadcastTensors() = DoubleTensorAlgebra { + fun testBroadcastTensors() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -51,7 +51,7 @@ internal class TestBroadcasting { } @Test - fun broadcastOuterTensors() = DoubleTensorAlgebra { + fun testBroadcastOuterTensors() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) @@ -68,7 +68,7 @@ internal class TestBroadcasting { } @Test - fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra { + fun testBroadcastOuterTensorsShapes() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) {0.0}) val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) {0.0}) val tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0)) @@ -81,7 +81,7 @@ internal class TestBroadcasting { } @Test - fun minusTensor() = BroadcastDoubleTensorAlgebra.invoke { + fun testMinusTensor() = BroadcastDoubleTensorAlgebra.invoke { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0)) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index ed5f8e780..132735cc7 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -15,14 +15,14 @@ import kotlin.test.assertTrue internal class TestDoubleTensor { @Test - fun valueTest() = DoubleTensorAlgebra { + fun testValue() = DoubleTensorAlgebra { val value = 12.5 val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) assertEquals(tensor.value(), value) } @Test - fun stridesTest() = DoubleTensorAlgebra { + fun testStrides() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) assertEquals(tensor[intArrayOf(0, 1)], 5.8) assertTrue( @@ -31,7 +31,7 @@ internal class TestDoubleTensor { } @Test - fun getTest() = DoubleTensorAlgebra { + fun testGet() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) val matrix = tensor[0].as2D() assertEquals(matrix[0, 1], 5.8) @@ -55,7 +55,7 @@ internal class TestDoubleTensor { } @Test - fun noBufferProtocol() { + fun testNoBufferProtocol() { // create buffer val doubleArray = DoubleBuffer(doubleArrayOf(1.0, 2.0, 3.0)) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index df2d21b96..d782d78d9 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -10,28 +10,28 @@ import kotlin.test.assertTrue internal class TestDoubleTensorAlgebra { @Test - fun doublePlus() = DoubleTensorAlgebra { + fun testDoublePlus() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(11.0, 12.0)) } @Test - fun doubleDiv() = DoubleTensorAlgebra { + fun TestDoubleDiv() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0)) val res = 2.0/tensor assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 0.5)) } @Test - fun divDouble() = DoubleTensorAlgebra { + fun testDivDouble() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0)) val res = tensor / 2.5 assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(4.0, 2.0)) } @Test - fun transpose1x1() = DoubleTensorAlgebra { + fun testTranspose1x1() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1), doubleArrayOf(0.0)) val res = tensor.transpose(0, 0) @@ -40,7 +40,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun transpose3x2() = DoubleTensorAlgebra { + fun testTranspose3x2() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = tensor.transpose(1, 0) @@ -49,7 +49,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun transpose1x2x3() = DoubleTensorAlgebra { + fun testTranspose1x2x3() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res01 = tensor.transpose(0, 1) val res02 = tensor.transpose(-3, 2) @@ -65,7 +65,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun linearStructure() = DoubleTensorAlgebra { + fun testLinearStructure() = DoubleTensorAlgebra { val shape = intArrayOf(3) val tensorA = full(value = -4.5, shape = shape) val tensorB = full(value = 10.9, shape = shape) @@ -97,7 +97,7 @@ internal class TestDoubleTensorAlgebra { } @Test - fun dot() = DoubleTensorAlgebra { + fun testDot() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor11 = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor2 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) @@ -118,22 +118,10 @@ internal class TestDoubleTensorAlgebra { val res11 = tensor1.dot(tensor11) assertTrue(res11.mutableBuffer.array() contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0)) assertTrue(res11.shape contentEquals intArrayOf(2, 2)) - - var tensor4 = fromArray(intArrayOf(10, 3, 4), DoubleArray(10 * 3 * 4) {0.0}) - var tensor5 = fromArray(intArrayOf(10, 4, 5), DoubleArray(10 * 4 * 5) {0.0}) - assertTrue(tensor4.dot(tensor5).shape contentEquals intArrayOf(10, 3, 5)) - - tensor4 = fromArray(intArrayOf(10, 3, 4), DoubleArray(10 * 3 * 4) {0.0}) - tensor5 = fromArray(intArrayOf(4, 5), DoubleArray(4 * 5) {0.0}) - assertTrue(tensor4.dot(tensor5).shape contentEquals intArrayOf(10, 3, 5)) - - tensor4 = fromArray(intArrayOf(4, 2, 1, 3, 8, 1), DoubleArray(4 * 2 * 1 * 3 * 8 * 1) {0.0}) - tensor5 = fromArray(intArrayOf(5, 1, 2, 8, 3, 1, 5), DoubleArray(5 * 1 * 2 * 8 * 3 * 1 * 5) {0.0}) - assertTrue(tensor4.dot(tensor5).shape contentEquals intArrayOf(5, 4, 2, 8, 3, 8, 5)) } @Test - fun diagonalEmbedding() = DoubleTensorAlgebra { + fun testDiagonalEmbedding() = DoubleTensorAlgebra { val tensor1 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0)) val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = zeros(intArrayOf(2, 3, 4, 5)) From 229c1b57daa3727a6e59d16c6ed04786a83ae220 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 6 May 2021 10:27:47 +0300 Subject: [PATCH 286/393] add documentation to DoubleLinearOpsTensorAlgebra --- .../tensors/api/LinearOpsTensorAlgebra.kt | 2 +- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 95 ++++++++++++++++++- 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 527e5d386..ec070b6bd 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -81,7 +81,7 @@ public interface LinearOpsTensorAlgebra : * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd * - * @return the determinant. + * @return triple `(U, S, V)`. */ public fun Tensor.svd(): Triple, Tensor, Tensor> diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index 89345e315..d17dc70fe 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -20,7 +20,10 @@ import space.kscience.kmath.tensors.core.luPivotHelper import space.kscience.kmath.tensors.core.pivInit import kotlin.math.min - +/** + * Implementation of common linear algebra operations on double numbers. + * Implements the LinearOpsTensorAlgebra interface. + */ public object DoubleLinearOpsTensorAlgebra : LinearOpsTensorAlgebra, DoubleTensorAlgebra() { @@ -29,12 +32,41 @@ public object DoubleLinearOpsTensorAlgebra : override fun Tensor.det(): DoubleTensor = detLU(1e-9) + /** + * Computes the LU factorization of a matrix or batches of matrices `input`. + * Returns a tuple containing the LU factorization and pivots of `input`. + * + * @param epsilon permissible error when comparing the determinant of a matrix with zero + * @return pair of `factorization` and `pivots`. + * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. + * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. + */ public fun Tensor.luFactor(epsilon: Double): Pair = computeLU(tensor, epsilon) ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") + /** + * Computes the LU factorization of a matrix or batches of matrices `input`. + * Returns a tuple containing the LU factorization and pivots of `input`. + * Uses an error of ``1e-9`` when calculating whether a matrix is degenerate. + * + * @return pair of `factorization` and `pivots`. + * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. + * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. + */ public fun Tensor.luFactor(): Pair = luFactor(1e-9) + /** + * Unpacks the data and pivots from a LU factorization of a tensor. + * Given a tensor [luTensor], return tensors (P, L, U) satisfying ``P * luTensor = L * U``, + * with `P` being a permutation matrix or batch of matrices, + * `L` being a lower triangular matrix or batch of matrices, + * `U` being an upper triangular matrix or batch of matrices. + * + * @param luTensor the packed LU factorization data + * @param pivotsTensor the packed LU factorization pivots + * @return triple of P, L and U tensors + */ public fun luPivot( luTensor: Tensor, pivotsTensor: Tensor @@ -66,6 +98,18 @@ public object DoubleLinearOpsTensorAlgebra : return Triple(pTensor, lTensor, uTensor) } + /** + * QR decomposition. + * + * Computes the QR decomposition of a matrix or a batch of matrices, and returns a pair `(Q, R)` of tensors. + * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q * R``, + * with `Q` being an orthogonal matrix or batch of orthogonal matrices + * and `R` being an upper triangular matrix or batch of upper triangular matrices. + * + * @param epsilon permissible error when comparing tensors for equality. + * Used when checking the positive definiteness of the input matrix or matrices. + * @return pair of Q and R tensors. + */ public fun Tensor.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) checkPositiveDefinite(tensor, epsilon) @@ -98,6 +142,18 @@ public object DoubleLinearOpsTensorAlgebra : override fun Tensor.svd(): Triple = svd(epsilon = 1e-10) + /** + * Singular Value Decomposition. + * + * Computes the singular value decomposition of either a matrix or batch of matrices `input`. + * The singular value decomposition is represented as a triple `(U, S, V)`, + * such that ``input = U.dot(diagonalEmbedding(S).dot(V.T))``. + * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. + * + * @param epsilon permissible error when calculating the dot product of vectors, + * i.e. the precision with which the cosine approaches 1 in an iterative algorithm. + * @return triple `(U, S, V)`. + */ public fun Tensor.svd(epsilon: Double): Triple { val size = tensor.linearStructure.dim val commonShape = tensor.shape.sliceArray(0 until size - 2) @@ -125,7 +181,14 @@ public object DoubleLinearOpsTensorAlgebra : override fun Tensor.symEig(): Pair = symEig(epsilon = 1e-15) - //For information: http://hua-zhou.github.io/teaching/biostatm280-2017spring/slides/16-eigsvd/eigsvd.html + /** + * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, + * represented by a pair (eigenvalues, eigenvectors). + * + * @param epsilon permissible error when comparing tensors for equality + * and when the cosine approaches 1 in the SVD algorithm. + * @return a pair (eigenvalues, eigenvectors) + */ public fun Tensor.symEig(epsilon: Double): Pair { checkSymmetric(tensor, epsilon) val (u, s, v) = tensor.svd(epsilon) @@ -139,6 +202,13 @@ public object DoubleLinearOpsTensorAlgebra : return eig to v } + /** + * Computes the determinant of a square matrix input, or of each square matrix in a batched input + * using LU factorization algorithm. + * + * @param epsilon error in the LU algorithm - permissible error when comparing the determinant of a matrix with zero + * @return the determinant. + */ public fun Tensor.detLU(epsilon: Double = 1e-9): DoubleTensor { checkSquareMatrix(tensor.shape) @@ -164,6 +234,15 @@ public object DoubleLinearOpsTensorAlgebra : return detTensor } + /** + * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input + * using LU factorization algorithm. + * Given a square matrix `a`, return the matrix `aInv` satisfying + * ``a.dot(aInv) = aInv.dot(a) = eye(a.shape[0])``. + * + * @param epsilon error in the LU algorithm - permissible error when comparing the determinant of a matrix with zero + * @return the multiplicative inverse of a matrix. + */ public fun Tensor.invLU(epsilon: Double = 1e-9): DoubleTensor { val (luTensor, pivotsTensor) = luFactor(epsilon) val invTensor = luTensor.zeroesLike() @@ -177,6 +256,18 @@ public object DoubleLinearOpsTensorAlgebra : return invTensor } + /** + * LUP decomposition + * + * Computes the LUP decomposition of a matrix or a batch of matrices. + * Given a tensor `input`, return tensors (P, L, U) satisfying ``P * input = L * U``, + * with `P` being a permutation matrix or batch of matrices, + * `L` being a lower triangular matrix or batch of matrices, + * `U` being an upper triangular matrix or batch of matrices. + * + * @param epsilon permissible error when comparing the determinant of a matrix with zero + * @return triple of P, L and U tensors + */ public fun Tensor.lu(epsilon: Double = 1e-9): Triple { val (lu, pivots) = this.luFactor(epsilon) return luPivot(lu, pivots) From a1cbd7a457a93619ad3033c66248b522137e4c46 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 6 May 2021 09:48:43 +0100 Subject: [PATCH 287/393] TensorLinearStructure doc --- .../kmath/tensors/core/algebras/TensorLinearStructure.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index 5fbc7390f..d69d342ad 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -56,7 +56,12 @@ internal fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { return res } - +/** + * This [Strides] implemetation follow the last dimension first convention + * For more information: https://numpy.org/doc/stable/reference/generated/numpy.ndarray.strides.html + * + * @param shape the shape of the tensor. + */ public class TensorLinearStructure(override val shape: IntArray) : Strides { override val strides: IntArray @@ -65,6 +70,7 @@ public class TensorLinearStructure(override val shape: IntArray) : Strides override fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) + // TODO: documentation (Alya) public fun stepIndex(index: IntArray): IntArray = stepIndex(index, shape, shape.size) From 477e64e4d396ebff3a66f487b2b0cab7f507e6bd Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 6 May 2021 09:51:59 +0100 Subject: [PATCH 288/393] Typos corrected --- .../kmath/tensors/core/algebras/TensorLinearStructure.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index d69d342ad..a5c01af55 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -57,7 +57,7 @@ internal fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { } /** - * This [Strides] implemetation follow the last dimension first convention + * This [Strides] implementation follows the last dimension first convention * For more information: https://numpy.org/doc/stable/reference/generated/numpy.ndarray.strides.html * * @param shape the shape of the tensor. From 16bed539977c516645d0a980f4f22578a6fbec11 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 6 May 2021 09:59:58 +0100 Subject: [PATCH 289/393] Drop unused functionality in TensorLinearStructure --- .../algebras/DoubleLinearOpsTensorAlgebra.kt | 2 +- .../core/algebras/TensorLinearStructure.kt | 27 +------------------ 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt index d17dc70fe..430482613 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt @@ -155,7 +155,7 @@ public object DoubleLinearOpsTensorAlgebra : * @return triple `(U, S, V)`. */ public fun Tensor.svd(epsilon: Double): Triple { - val size = tensor.linearStructure.dim + val size = tensor.dimension val commonShape = tensor.shape.sliceArray(0 until size - 2) val (n, m) = tensor.shape.sliceArray(size - 2 until size) val uTensor = zeros(commonShape + intArrayOf(min(n, m), n)) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index a5c01af55..68aa03311 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -39,45 +39,20 @@ internal fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArra return res } -internal fun stepIndex(index: IntArray, shape: IntArray, nDim: Int): IntArray { - val res = index.copyOf() - var current = nDim - 1 - var carry = 0 - - do { - res[current]++ - if (res[current] >= shape[current]) { - carry = 1 - res[current] = 0 - } - current-- - } while (carry != 0 && current >= 0) - - return res -} - /** * This [Strides] implementation follows the last dimension first convention * For more information: https://numpy.org/doc/stable/reference/generated/numpy.ndarray.strides.html * * @param shape the shape of the tensor. */ -public class TensorLinearStructure(override val shape: IntArray) : Strides -{ +public class TensorLinearStructure(override val shape: IntArray) : Strides { override val strides: IntArray get() = stridesFromShape(shape) override fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) - // TODO: documentation (Alya) - public fun stepIndex(index: IntArray): IntArray = - stepIndex(index, shape, shape.size) - override val linearSize: Int get() = shape.reduce(Int::times) - public val dim: Int - get() = shape.size - } \ No newline at end of file From 499cf85ff08ac65e7343e33af2f4f65cd9967b3f Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Thu, 6 May 2021 12:30:13 +0300 Subject: [PATCH 290/393] refactor BT + docs --- .../kmath/tensors/core/BufferedTensor.kt | 112 ++++-------------- .../kmath/tensors/core/DoubleTensor.kt | 19 +++ .../kscience/kmath/tensors/core/IntTensor.kt | 17 +++ .../kmath/tensors/core/tensorCasts.kt | 36 ++++++ .../kmath/tensors/core/tensorCastsUtils.kt | 42 +++++++ 5 files changed, 136 insertions(+), 90 deletions(-) create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 22a1ef1bf..e4ffccd96 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,116 +1,48 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure - -public open class BufferedTensor( +/** + * [Tensor] implementation provided with [MutableBuffer] + */ +public open class BufferedTensor internal constructor( override val shape: IntArray, internal val mutableBuffer: MutableBuffer, internal val bufferStart: Int ) : Tensor { + + /** + * [TensorLinearStructure] with the same shape + */ public val linearStructure: TensorLinearStructure get() = TensorLinearStructure(shape) + /** + * Number of elements in tensor + */ public val numElements: Int get() = linearStructure.linearSize + /** + * @param index [IntArray] with size equal to tensor dimension + * @return the element by multidimensional index + */ override fun get(index: IntArray): T = mutableBuffer[bufferStart + linearStructure.offset(index)] + /** + * @param index the [IntArray] with size equal to tensor dimension + * @param value the value to set + */ override fun set(index: IntArray, value: T) { mutableBuffer[bufferStart + linearStructure.offset(index)] = value } + /** + * @return the sequence of pairs multidimensional indices and values + */ override fun elements(): Sequence> = linearStructure.indices().map { it to this[it] } } - -public class IntTensor internal constructor( - shape: IntArray, - buffer: IntArray, - offset: Int = 0 -) : BufferedTensor(shape, IntBuffer(buffer), offset) - -public class DoubleTensor internal constructor( - shape: IntArray, - buffer: DoubleArray, - offset: Int = 0 -) : BufferedTensor(shape, DoubleBuffer(buffer), offset) { - override fun toString(): String = toPrettyString() -} - -internal fun BufferedTensor.asTensor(): IntTensor = - IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) - -internal fun BufferedTensor.asTensor(): DoubleTensor = - DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) - -internal fun Tensor.copyToBufferedTensor(): BufferedTensor = - BufferedTensor( - this.shape, - TensorLinearStructure(this.shape).indices().map(this::get).toMutableList().asMutableBuffer(), 0 - ) - -internal fun Tensor.toBufferedTensor(): BufferedTensor = when (this) { - is BufferedTensor -> this - is MutableBufferND -> if (this.strides.strides contentEquals TensorLinearStructure(this.shape).strides) - BufferedTensor(this.shape, this.mutableBuffer, 0) else this.copyToBufferedTensor() - else -> this.copyToBufferedTensor() -} - -internal val Tensor.tensor: DoubleTensor - get() = when (this) { - is DoubleTensor -> this - else -> this.toBufferedTensor().asTensor() - } - -internal val Tensor.tensor: IntTensor - get() = when (this) { - is IntTensor -> this - else -> this.toBufferedTensor().asTensor() - } - -public fun Tensor.toDoubleTensor(): DoubleTensor = this.tensor -public fun Tensor.toIntTensor(): IntTensor = this.tensor - -public fun Array.toDoubleTensor(): DoubleTensor { - val n = size - check(n > 0) { "An empty array cannot be casted to tensor" } - val m = first().size - check(m > 0) { "Inner arrays must have at least 1 argument" } - check(all { size == m }) { "Inner arrays must be the same size" } - - val shape = intArrayOf(n, m) - val buffer = this.flatMap { arr -> arr.map { it } }.toDoubleArray() - - return DoubleTensor(shape, buffer, 0) -} - - -public fun Array.toIntTensor(): IntTensor { - val n = size - check(n > 0) { "An empty array cannot be casted to tensor" } - val m = first().size - check(m > 0) { "Inner arrays must have at least 1 argument" } - check(all { size == m }) { "Inner arrays must be the same size" } - - val shape = intArrayOf(n, m) - val buffer = this.flatMap { arr -> arr.map { it } }.toIntArray() - - return IntTensor(shape, buffer, 0) -} - -public fun DoubleTensor.toDoubleArray(): DoubleArray { - return DoubleArray(numElements) { i -> - mutableBuffer[bufferStart + i] - } -} - -public fun IntTensor.toIntArray(): IntArray { - return IntArray(numElements) { i -> - mutableBuffer[bufferStart + i] - } -} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt new file mode 100644 index 000000000..e3143f5a7 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt @@ -0,0 +1,19 @@ +/* + * 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.tensors.core + +import space.kscience.kmath.structures.DoubleBuffer + +/** + * Default [BufferedTensor] implementation for [Double] values + */ +public class DoubleTensor internal constructor( + shape: IntArray, + buffer: DoubleArray, + offset: Int = 0 +) : BufferedTensor(shape, DoubleBuffer(buffer), offset) { + override fun toString(): String = toPrettyString() +} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt new file mode 100644 index 000000000..ae1e6c8c8 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt @@ -0,0 +1,17 @@ +/* + * 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.tensors.core + +import space.kscience.kmath.structures.IntBuffer + +/** + * Default [BufferedTensor] implementation for [Int] values + */ +public class IntTensor internal constructor( + shape: IntArray, + buffer: IntArray, + offset: Int = 0 +) : BufferedTensor(shape, IntBuffer(buffer), offset) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt new file mode 100644 index 000000000..6254ce751 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt @@ -0,0 +1,36 @@ +/* + * 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.tensors.core + +import space.kscience.kmath.tensors.api.Tensor + +/** + * Casts [Tensor] to [DoubleTensor] + */ +public fun Tensor.toDoubleTensor(): DoubleTensor = this.tensor + +/** + * Casts [Tensor] to [IntTensor] + */ +public fun Tensor.toIntTensor(): IntTensor = this.tensor + +/** + * @return [DoubleArray] of tensor elements + */ +public fun DoubleTensor.toDoubleArray(): DoubleArray { + return DoubleArray(numElements) { i -> + mutableBuffer[bufferStart + i] + } +} + +/** + * @return [IntArray] of tensor elements + */ +public fun IntTensor.toIntArray(): IntArray { + return IntArray(numElements) { i -> + mutableBuffer[bufferStart + i] + } +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt new file mode 100644 index 000000000..31de6919f --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt @@ -0,0 +1,42 @@ +/* + * 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.tensors.core + +import space.kscience.kmath.nd.MutableBufferND +import space.kscience.kmath.structures.asMutableBuffer +import space.kscience.kmath.tensors.api.Tensor +import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure + +internal fun BufferedTensor.asTensor(): IntTensor = + IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) + +internal fun BufferedTensor.asTensor(): DoubleTensor = + DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) + +internal fun Tensor.copyToBufferedTensor(): BufferedTensor = + BufferedTensor( + this.shape, + TensorLinearStructure(this.shape).indices().map(this::get).toMutableList().asMutableBuffer(), 0 + ) + +internal fun Tensor.toBufferedTensor(): BufferedTensor = when (this) { + is BufferedTensor -> this + is MutableBufferND -> if (this.strides.strides contentEquals TensorLinearStructure(this.shape).strides) + BufferedTensor(this.shape, this.mutableBuffer, 0) else this.copyToBufferedTensor() + else -> this.copyToBufferedTensor() +} + +internal val Tensor.tensor: DoubleTensor + get() = when (this) { + is DoubleTensor -> this + else -> this.toBufferedTensor().asTensor() + } + +internal val Tensor.tensor: IntTensor + get() = when (this) { + is IntTensor -> this + else -> this.toBufferedTensor().asTensor() + } \ No newline at end of file From 35928e7960bd5676820b751490be057fa62409ff Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 6 May 2021 10:52:37 +0100 Subject: [PATCH 291/393] minor corrections --- .../kscience/kmath/tensors/core/BufferedTensor.kt | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index e4ffccd96..e8c0556c2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -5,7 +5,7 @@ import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure /** - * [Tensor] implementation provided with [MutableBuffer] + * Represents [Tensor] over a [MutableBuffer] intended to be used through [DoubleTensor] and [IntTensor] */ public open class BufferedTensor internal constructor( override val shape: IntArray, @@ -14,7 +14,7 @@ public open class BufferedTensor internal constructor( ) : Tensor { /** - * [TensorLinearStructure] with the same shape + * Buffer strides based on [TensorLinearStructure] implementation */ public val linearStructure: TensorLinearStructure get() = TensorLinearStructure(shape) @@ -25,23 +25,12 @@ public open class BufferedTensor internal constructor( public val numElements: Int get() = linearStructure.linearSize - /** - * @param index [IntArray] with size equal to tensor dimension - * @return the element by multidimensional index - */ override fun get(index: IntArray): T = mutableBuffer[bufferStart + linearStructure.offset(index)] - /** - * @param index the [IntArray] with size equal to tensor dimension - * @param value the value to set - */ override fun set(index: IntArray, value: T) { mutableBuffer[bufferStart + linearStructure.offset(index)] = value } - /** - * @return the sequence of pairs multidimensional indices and values - */ override fun elements(): Sequence> = linearStructure.indices().map { it to this[it] } From 8ac253b9fe112bfe64d467c07db9dc9b9ed74e52 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Thu, 6 May 2021 14:09:47 +0300 Subject: [PATCH 292/393] cov + docs --- .../tensors/api/AnalyticTensorAlgebra.kt | 10 +++++++ .../algebras/DoubleAnalyticTensorAlgebra.kt | 24 ++++++++++++++++- .../core/algebras/DoubleTensorAlgebra.kt | 27 +++++++++++++------ 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index aa5678b31..69e88c28f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -68,6 +68,16 @@ public interface AnalyticTensorAlgebra : */ public fun Tensor.variance(dim: Int, keepDim: Boolean): Tensor + /** + * Returns the covariance matrix M of given vectors. + * + * M[i, j] contains covariance of i-th and j-th given vectors + * + * @param tensors the [List] of 1-dimensional tensors with same shape + * @return the covariance matrix + */ + public fun cov(tensors: List>): Tensor + //For information: https://pytorch.org/docs/stable/generated/torch.exp.html public fun Tensor.exp(): Tensor diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt index 4a1f360e3..23a2fa282 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt @@ -57,6 +57,28 @@ public object DoubleAnalyticTensorAlgebra : keepDim ) + private fun cov(x: DoubleTensor, y:DoubleTensor): Double{ + val n = x.shape[0] + return ((x - x.mean()) * (y - y.mean())).mean() * n / (n - 1) + } + + override fun cov(tensors: List>): DoubleTensor { + check(tensors.isNotEmpty()) { "List must have at least 1 element" } + val n = tensors.size + val m = tensors[0].shape[0] + check(tensors.all { it.shape contentEquals intArrayOf(m) }) { "Tensors must have same shapes" } + val resTensor = DoubleTensor( + intArrayOf(n, n), + DoubleArray(n * n) {0.0} + ) + for (i in 0 until n){ + for (j in 0 until n){ + resTensor[intArrayOf(i, j)] = cov(tensors[i].tensor, tensors[j].tensor) + } + } + return resTensor + } + override fun Tensor.exp(): DoubleTensor = tensor.map(::exp) override fun Tensor.ln(): DoubleTensor = tensor.map(::ln) @@ -91,4 +113,4 @@ public object DoubleAnalyticTensorAlgebra : override fun Tensor.floor(): DoubleTensor = tensor.map(::floor) -} \ No newline at end of file +} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index d220bdd9a..74ef63ab7 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -401,19 +401,31 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public fun Tensor.randomNormalLike(seed: Long = 0): DoubleTensor = DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) - // stack tensors by axis 0 - public fun stack(tensors: List): DoubleTensor { - val shape = tensors.firstOrNull()?.shape - check(shape != null) { "Collection must have at least 1 element" } - check(tensors.all { it.shape contentEquals shape }) { "Stacking tensors must have same shapes" } + /** + * Concatenates a sequence of tensors along a new dimension. + * + * @param tensors the [List] of tensors with same shapes to concatenate + * @param dim the dimension to insert + * @return tensor with concatenation result + */ + public fun stack(tensors: List>, dim: Int = 0): DoubleTensor { + check(dim == 0) { "Stack by non-zero dimension not implemented yet" } + check(tensors.isNotEmpty()) { "List must have at least 1 element" } + val shape = tensors[0].shape + check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } val resShape = intArrayOf(tensors.size) + shape val resBuffer = tensors.flatMap { - it.tensor.mutableBuffer.array().drop(it.bufferStart).take(it.numElements) + it.tensor.mutableBuffer.array().drop(it.tensor.bufferStart).take(it.tensor.numElements) }.toDoubleArray() return DoubleTensor(resShape, resBuffer, 0) } - // build tensor from this rows by given indices + /** + * Build tensor from rows of input tensor + * + * @param indices the [IntArray] of 1-dimensional indices + * @return tensor with rows corresponding to rows by [indices] + */ public fun Tensor.rowsByIndices(indices: IntArray): DoubleTensor { return stack(indices.map { this[it] }) } @@ -450,7 +462,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun Tensor.sum(dim: Int, keepDim: Boolean): DoubleTensor = foldDim({ x -> x.sum() }, dim, keepDim) - override fun Tensor.min(): Double = this.fold { it.minOrNull()!! } override fun Tensor.min(dim: Int, keepDim: Boolean): DoubleTensor = From dc22bd84986d14f6d82209a106d6413e3bd609e2 Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 6 May 2021 14:23:57 +0300 Subject: [PATCH 293/393] add documentation to DoubleTensorAlgebra --- .../core/algebras/DoubleTensorAlgebra.kt | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index d220bdd9a..2cad85a09 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -23,6 +23,9 @@ import space.kscience.kmath.tensors.core.getRandomNormals import space.kscience.kmath.tensors.core.minusIndexFrom import kotlin.math.abs +/** + * Implementation of basic operations over double tensors and basic algebra operations on them. + */ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { public companion object : DoubleTensorAlgebra() @@ -34,6 +37,13 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return tensor.mutableBuffer.array()[tensor.bufferStart] } + /** + * Constructs a tensor with the specified shape and data. + * + * @param shape the desired shape for the tensor. + * @param buffer one-dimensional data array. + * @return tensor with the [shape] shape and [buffer] data. + */ public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor { checkEmptyShape(shape) checkEmptyDoubleBuffer(buffer) @@ -48,26 +58,67 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(newShape, tensor.mutableBuffer.array(), newStart) } + /** + * Creates a tensor of a given shape and fills all elements with a given value. + * + * @param value the value to fill the output tensor with. + * @param shape array of integers defining the shape of the output tensor. + * @return tensor with the [shape] shape and filled with [value]. + */ public fun full(value: Double, shape: IntArray): DoubleTensor { checkEmptyShape(shape) val buffer = DoubleArray(shape.reduce(Int::times)) { value } return DoubleTensor(shape, buffer) } + /** + * Returns a tensor with the same shape as `input` filled with [value]. + * + * @param value the value to fill the output tensor with. + * @return tensor with the `input` tensor shape and filled with [value]. + */ public fun Tensor.fullLike(value: Double): DoubleTensor { val shape = tensor.shape val buffer = DoubleArray(tensor.numElements) { value } return DoubleTensor(shape, buffer) } + /** + * Returns a tensor filled with the scalar value 0.0, with the shape defined by the variable argument [shape]. + * + * @param shape array of integers defining the shape of the output tensor. + * @return tensor filled with the scalar value 0.0, with the [shape] shape. + */ public fun zeros(shape: IntArray): DoubleTensor = full(0.0, shape) + /** + * Returns a tensor filled with the scalar value 0.0, with the same shape as a given array. + * + * @return tensor filled with the scalar value 0.0, with the same shape as `input` tensor. + */ public fun Tensor.zeroesLike(): DoubleTensor = tensor.fullLike(0.0) + /** + * Returns a tensor filled with the scalar value 1.0, with the shape defined by the variable argument [shape]. + * + * @param shape array of integers defining the shape of the output tensor. + * @return tensor filled with the scalar value 1.0, with the [shape] shape. + */ public fun ones(shape: IntArray): DoubleTensor = full(1.0, shape) + /** + * Returns a tensor filled with the scalar value 1.0, with the same shape as a given array. + * + * @return tensor filled with the scalar value 1.0, with the same shape as `input` tensor. + */ public fun Tensor.onesLike(): DoubleTensor = tensor.fullLike(1.0) + /** + * Returns a 2-D tensor with shape ([n], [n]), with ones on the diagonal and zeros elsewhere. + * + * @param n the number of rows and columns + * @return a 2-D tensor with ones on the diagonal and zeros elsewhere. + */ public fun eye(n: Int): DoubleTensor { val shape = intArrayOf(n, n) val buffer = DoubleArray(n * n) { 0.0 } @@ -78,6 +129,11 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return res } + /** + * Return a copy of the tensor. + * + * @return a copy of the `input` tensor with a copied buffer. + */ public fun Tensor.copy(): DoubleTensor { return DoubleTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart) } @@ -359,7 +415,6 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return resTensor.tensor } - public fun Tensor.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( tensor.shape, From 90149e396561004e781b390f87c51361e6a9e82f Mon Sep 17 00:00:00 2001 From: AlyaNovikova Date: Thu, 6 May 2021 14:42:15 +0300 Subject: [PATCH 294/393] add documentation to map and randomNormal function --- .../core/algebras/DoubleTensorAlgebra.kt | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index d8b59daa7..8c76de0de 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -415,6 +415,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return resTensor.tensor } + /** + * Applies the [transform] function to each element of the tensor and returns the resulting modified tensor. + * + * @param transform the function to be applied to each element of the tensor. + * @return the resulting tensor after applying the function. + */ public fun Tensor.map(transform: (Double) -> Double): DoubleTensor { return DoubleTensor( tensor.shape, @@ -423,10 +429,24 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { ) } + /** + * Compares element-wise two tensors with a specified precision. + * + * @param other the tensor to compare with `input` tensor. + * @param epsilon permissible error when comparing two Double values. + * @return true if two tensors have the same shape and elements, false otherwise. + */ public fun Tensor.eq(other: Tensor, epsilon: Double): Boolean { return tensor.eq(other) { x, y -> abs(x - y) < epsilon } } + /** + * Compares element-wise two tensors. + * Comparison of two Double values occurs with 1e-5 precision. + * + * @param other the tensor to compare with `input` tensor. + * @return true if two tensors have the same shape and elements, false otherwise. + */ public infix fun Tensor.eq(other: Tensor): Boolean = tensor.eq(other, 1e-5) private fun Tensor.eq( @@ -450,9 +470,25 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return true } + /** + * Returns a tensor of random numbers drawn from normal distributions with 0.0 mean and 1.0 standard deviation. + * + * @param shape the desired shape for the output tensor. + * @param seed the random seed of the pseudo-random number generator. + * @return tensor of a given shape filled with numbers from the normal distribution + * with 0.0 mean and 1.0 standard deviation. + */ public fun randomNormal(shape: IntArray, seed: Long = 0): DoubleTensor = DoubleTensor(shape, getRandomNormals(shape.reduce(Int::times), seed)) + /** + * Returns a tensor with the same shape as `input` of random numbers drawn from normal distributions + * with 0.0 mean and 1.0 standard deviation. + * + * @param seed the random seed of the pseudo-random number generator. + * @return tensor with the same shape as `input` filled with numbers from the normal distribution + * with 0.0 mean and 1.0 standard deviation. + */ public fun Tensor.randomNormalLike(seed: Long = 0): DoubleTensor = DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) From 5fe1320855941167afba93fb0f3d0beb855c834e Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 6 May 2021 12:59:21 +0100 Subject: [PATCH 295/393] minor corrections --- .../kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 8c76de0de..1c8eacf66 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -493,7 +493,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) /** - * Concatenates a sequence of tensors along a new dimension. + * Concatenates a sequence of tensors along the first dimension. * * @param tensors the [List] of tensors with same shapes to concatenate * @param dim the dimension to insert From db5378c9f4ab3ff4e84d815d9db4686015330bf9 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Thu, 6 May 2021 16:29:21 +0300 Subject: [PATCH 296/393] PCA example --- .../space/kscience/kmath/tensors/PCA.kt | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt new file mode 100644 index 000000000..1d72b2326 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -0,0 +1,78 @@ +/* + * 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.tensors + +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra + +const val seed = 100500L + +// simple PCA + +fun main(){ + DoubleAnalyticTensorAlgebra { + + // assume x is range from 0 until 10 + val x = fromArray( + intArrayOf(10), + (0 until 10).toList().map { it.toDouble() }.toDoubleArray() + ) + + // take y dependent on x with noise + val y = 2.0 * x + (3.0 + x.randomNormalLike(seed) * 1.5) + + println("x:\n$x") + println("y:\n$y") + + // stack them into single dataset + val dataset = stack(listOf(x, y)).transpose() + + // normalize both x and y + val xMean = x.mean() + val yMean = y.mean() + + val xStd = x.std() + val yStd = y.std() + + val xScaled = (x - xMean) / xStd + val yScaled = (y - yMean) / yStd + + // save means ans standard deviations for further recovery + val mean = fromArray( + intArrayOf(2), + doubleArrayOf(xMean, yMean) + ) + println("Means:\n$mean") + + val std = fromArray( + intArrayOf(2), + doubleArrayOf(xStd, yStd) + ) + println("Standard deviations:\n$std") + + // calculate the covariance matrix of scaled x and y + val covMatrix = cov(listOf(xScaled, yScaled)) + println("Covariance matrix:\n$covMatrix") + + // and find out eigenvector of it + val (_, evecs) = DoubleLinearOpsTensorAlgebra {covMatrix.symEig()} + val v = evecs[0] + println("Eigenvector:\n$v") + + // reduce dimension of dataset + val datasetReduced = v dot stack(listOf(xScaled, yScaled)) + println("Reduced data:\n$datasetReduced") + + // we can restore original data from reduced data. + // for example, find 7th element of dataset + val n = 7 + val restored = BroadcastDoubleTensorAlgebra{(datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean} + println("Original value:\n${dataset[n]}") + println("Restored value:\n$restored") + } +} From febe526325150c2b716f233956a12e69fcb44804 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 6 May 2021 14:50:05 +0100 Subject: [PATCH 297/393] Update stack docs --- .../kmath/tensors/core/algebras/DoubleTensorAlgebra.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 1c8eacf66..9500fbdec 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -493,14 +493,12 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) /** - * Concatenates a sequence of tensors along the first dimension. + * Concatenates a sequence of tensors with equal shapes along the first dimension. * * @param tensors the [List] of tensors with same shapes to concatenate - * @param dim the dimension to insert * @return tensor with concatenation result */ - public fun stack(tensors: List>, dim: Int = 0): DoubleTensor { - check(dim == 0) { "Stack by non-zero dimension not implemented yet" } + public fun stack(tensors: List>): DoubleTensor { check(tensors.isNotEmpty()) { "List must have at least 1 element" } val shape = tensors[0].shape check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } From 1b1a078deaee681c99603737d11eecefe0411db4 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 7 May 2021 03:22:34 +0300 Subject: [PATCH 298/393] neural network! --- .../kscience/kmath/tensors/NeuralNetwork.kt | 245 ++++++++++++++++++ .../space/kscience/kmath/tensors/PCA.kt | 5 +- .../kmath/tensors/api/TensorAlgebra.kt | 13 +- .../core/algebras/DoubleTensorAlgebra.kt | 5 + 4 files changed, 266 insertions(+), 2 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt new file mode 100644 index 000000000..ea863988c --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt @@ -0,0 +1,245 @@ +/* + * 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.tensors + +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.toDoubleArray +import kotlin.math.sqrt + +const val seed = 100500L + +// Simple feedforward neural network with backpropagation training + +// interface of network layer +interface Layer { + fun forward(input: DoubleTensor): DoubleTensor + fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor +} + +// activation layer +open class Activation( + val activation: (DoubleTensor) -> DoubleTensor, + val activationDer: (DoubleTensor) -> DoubleTensor +) : Layer { + override fun forward(input: DoubleTensor): DoubleTensor { + return activation(input) + } + + override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor { + return DoubleTensorAlgebra { outputError * activationDer(input) } + } +} + +fun relu(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { + x.map { if (it > 0) it else 0.0 } +} + +fun reluDer(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { + x.map { if (it > 0) 1.0 else 0.0 } +} + +// activation layer with relu activator +class ReLU : Activation(::relu, ::reluDer) + +fun sigmoid(x: DoubleTensor): DoubleTensor = DoubleAnalyticTensorAlgebra { + 1.0 / (1.0 + (-x).exp()) +} + +fun sigmoidDer(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { + sigmoid(x) * (1.0 - sigmoid(x)) +} + +// activation layer with sigmoid activator +class Sigmoid : Activation(::sigmoid, ::sigmoidDer) + +// dense layer +class Dense( + private val inputUnits: Int, + private val outputUnits: Int, + private val learningRate: Double = 0.1 +) : Layer { + + private val weights: DoubleTensor = DoubleTensorAlgebra { + randomNormal( + intArrayOf(inputUnits, outputUnits), + seed + ) * sqrt(2.0 / (inputUnits + outputUnits)) + } + + private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(intArrayOf(outputUnits)) } + + override fun forward(input: DoubleTensor): DoubleTensor { + return BroadcastDoubleTensorAlgebra { (input dot weights) + bias } + } + + override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { + val gradInput = outputError dot weights.transpose() + + val gradW = input.transpose() dot outputError + val gradBias = DoubleAnalyticTensorAlgebra { + outputError.mean(dim = 0, keepDim = false) * input.shape[0].toDouble() + } + + weights -= learningRate * gradW + bias -= learningRate * gradBias + + gradInput + } + +} + +// simple accuracy equal to the proportion of correct answers +fun accuracy(yPred: DoubleTensor, yTrue: DoubleTensor): Double { + check(yPred.shape contentEquals yTrue.shape) + val n = yPred.shape[0] + var correctCnt = 0 + for (i in 0 until n) { + if (yPred[intArrayOf(i, 0)] == yTrue[intArrayOf(i, 0)]) { + correctCnt += 1 + } + } + return correctCnt.toDouble() / n.toDouble() +} + +// neural network class +class NeuralNetwork(private val layers: List) { + private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = DoubleAnalyticTensorAlgebra { + + val onesForAnswers = yPred.zeroesLike() + yTrue.toDoubleArray().forEachIndexed { index, labelDouble -> + val label = labelDouble.toInt() + onesForAnswers[intArrayOf(index, label)] = 1.0 + } + + val softmaxValue = BroadcastDoubleTensorAlgebra { yPred.exp() / yPred.exp().sum(dim = 1, keepDim = true) } + + (-onesForAnswers + softmaxValue) / (yPred.shape[0].toDouble()) + } + + @OptIn(ExperimentalStdlibApi::class) + private fun forward(x: DoubleTensor): List { + var input = x + + return buildList { + layers.forEach { layer -> + val output = layer.forward(input) + add(output) + input = output + } + } + } + + @OptIn(ExperimentalStdlibApi::class) + private fun train(xTrain: DoubleTensor, yTrain: DoubleTensor) { + val layerInputs = buildList { + add(xTrain) + addAll(forward(xTrain)) + } + + var lossGrad = softMaxLoss(layerInputs.last(), yTrain) + + layers.zip(layerInputs).reversed().forEach { (layer, input) -> + lossGrad = layer.backward(input, lossGrad) + } + } + + fun fit(xTrain: DoubleTensor, yTrain: DoubleTensor, batchSize: Int, epochs: Int) = DoubleTensorAlgebra { + fun iterBatch(x: DoubleTensor, y: DoubleTensor): Sequence> = sequence { + val n = x.shape[0] + val shuffledIndices = (0 until n).shuffled() + for (i in 0 until n step batchSize) { + val excerptIndices = shuffledIndices.drop(i).take(batchSize).toIntArray() + val batch = x.rowsByIndices(excerptIndices) to y.rowsByIndices(excerptIndices) + yield(batch) + } + } + + for (epoch in 0 until epochs) { + println("Epoch ${epoch + 1}/$epochs") + for ((xBatch, yBatch) in iterBatch(xTrain, yTrain)) { + train(xBatch, yBatch) + } + println("Accuracy:${accuracy(yTrain, predict(xTrain).argMax(1, true))}") + } + } + + fun predict(x: DoubleTensor): DoubleTensor { + return forward(x).last() + } + +} + + + +@OptIn(ExperimentalStdlibApi::class) +fun main() { + DoubleTensorAlgebra { + val features = 5 + val sampleSize = 250 + val trainSize = 180 + val testSize = sampleSize - trainSize + + // take sample of features from normal distribution + val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5 + BroadcastDoubleTensorAlgebra { + x += fromArray( + intArrayOf(5), + doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means + ) + } + + // define class like '1' if the sum of features > 0 and '0' otherwise + val y = fromArray( + intArrayOf(sampleSize, 1), + DoubleArray(sampleSize) { i -> + if (x[i].sum() > 0.0) { + 1.0 + } else { + 0.0 + } + } + ) + + // split train ans test + val trainIndices = (0 until trainSize).toList().toIntArray() + val testIndices = (trainSize until sampleSize).toList().toIntArray() + + val xTrain = x.rowsByIndices(trainIndices) + val yTrain = y.rowsByIndices(trainIndices) + + val xTest = x.rowsByIndices(testIndices) + val yTest = y.rowsByIndices(testIndices) + + // build model + val layers = buildList { + add(Dense(features, 64)) + add(ReLU()) + add(Dense(64, 16)) + add(ReLU()) + add(Dense(16, 2)) + add(Sigmoid()) + } + val model = NeuralNetwork(layers) + + // fit it with train data + model.fit(xTrain, yTrain, batchSize = 20, epochs = 10) + + // make prediction + val prediction = model.predict(xTest) + + // process raw prediction via argMax + val predictionLabels = prediction.argMax(1, true) + + // find out accuracy + val acc = accuracy(yTest, predictionLabels) + println("Test accuracy:$acc") + + } +} diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt index 1d72b2326..ee25b63a3 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -10,11 +10,14 @@ import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra -const val seed = 100500L + // simple PCA fun main(){ + val seed = 100500L + + // work in context with analytic methods DoubleAnalyticTensorAlgebra { // assume x is range from 0 until 10 diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index b0a0f9618..417cff87f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -305,5 +305,16 @@ public interface TensorAlgebra: Algebra> { */ public fun Tensor.max(dim: Int, keepDim: Boolean): Tensor - + /** + * Returns the index of maximum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the the index of maximum value of each row of the input tensor in the given dimension [dim]. + */ + public fun Tensor.argMax(dim: Int, keepDim: Boolean): Tensor } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 9500fbdec..6fac0a0ec 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -561,4 +561,9 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { override fun Tensor.max(dim: Int, keepDim: Boolean): DoubleTensor = foldDim({ x -> x.maxOrNull()!! }, dim, keepDim) + override fun Tensor.argMax(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim({ x -> + x.withIndex().maxByOrNull { it.value }?.index!!.toDouble() + }, dim, keepDim) + } From 14ca7cdd31e14855c95a51b8143bf80aae02feb9 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 7 May 2021 13:00:20 +0300 Subject: [PATCH 299/393] fixes --- .../kmath/tensors/api/LinearOpsTensorAlgebra.kt | 15 ++++++++------- .../kscience/kmath/tensors/api/TensorAlgebra.kt | 2 +- .../tensors/core/algebras/DoubleTensorAlgebra.kt | 9 ++++----- .../core/algebras/TensorLinearStructure.kt | 3 +-- .../kscience/kmath/tensors/core/tensorCasts.kt | 2 +- .../kmath/tensors/core/tensorCastsUtils.kt | 2 +- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index ec070b6bd..4a325ab4e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -23,8 +23,8 @@ public interface LinearOpsTensorAlgebra : /** * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input. - * Given a square matrix `a`, return the matrix `aInv` satisfying - * ``a.dot(aInv) = aInv.dot(a) = eye(a.shape[0])``. + * Given a square matrix `A`, return the matrix `AInv` satisfying + * `A dot AInv = AInv dot A = eye(a.shape[0])`. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.inv * * @return the multiplicative inverse of a matrix. @@ -37,7 +37,7 @@ public interface LinearOpsTensorAlgebra : * Computes the Cholesky decomposition of a Hermitian (or symmetric for real-valued matrices) * positive-definite matrix or the Cholesky decompositions for a batch of such matrices. * Each decomposition has the form: - * Given a tensor `input`, return the tensor `L` satisfying ``input = L * L.H``, + * Given a tensor `input`, return the tensor `L` satisfying `input = L dot L.H`, * where L is a lower-triangular matrix and L.H is the conjugate transpose of L, * which is just a transpose for the case of real-valued input matrices. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.cholesky @@ -50,7 +50,7 @@ public interface LinearOpsTensorAlgebra : * QR decomposition. * * Computes the QR decomposition of a matrix or a batch of matrices, and returns a pair `(Q, R)` of tensors. - * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q * R``, + * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q dot R``, * with `Q` being an orthogonal matrix or batch of orthogonal matrices * and `R` being an upper triangular matrix or batch of upper triangular matrices. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.qr @@ -63,7 +63,7 @@ public interface LinearOpsTensorAlgebra : * LUP decomposition * * Computes the LUP decomposition of a matrix or a batch of matrices. - * Given a tensor `input`, return tensors (P, L, U) satisfying ``P * input = L * U``, + * Given a tensor `input`, return tensors (P, L, U) satisfying `P dot input = L dot U`, * with `P` being a permutation matrix or batch of matrices, * `L` being a lower triangular matrix or batch of matrices, * `U` being an upper triangular matrix or batch of matrices. @@ -77,7 +77,8 @@ public interface LinearOpsTensorAlgebra : * * Computes the singular value decomposition of either a matrix or batch of matrices `input`. * The singular value decomposition is represented as a triple `(U, S, V)`, - * such that ``input = U.dot(diagonalEmbedding(S).dot(V.T))``. + * such that `input = U dot diagonalEmbedding(S) dot V.H`, + * where V.H is the conjugate transpose of V. * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. * For more information: https://pytorch.org/docs/stable/linalg.html#torch.linalg.svd * @@ -94,4 +95,4 @@ public interface LinearOpsTensorAlgebra : */ public fun Tensor.symEig(): Pair, Tensor> -} \ No newline at end of file +} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 417cff87f..e7f8dc7ae 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -288,7 +288,7 @@ public interface TensorAlgebra: Algebra> { public fun Tensor.min(dim: Int, keepDim: Boolean): Tensor /** - * @return the maximum value of all elements in the input tensor. + * Returns the maximum value of all elements in the input tensor. */ public fun Tensor.max(): T diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index 6fac0a0ec..e5d41f856 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -343,7 +343,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { val m2 = newOther.shape[newOther.shape.size - 2] val n = newOther.shape[newOther.shape.size - 1] check(m1 == m2) { - throw RuntimeException("Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)") + "Tensors dot operation dimension mismatch: ($l, $m1) x ($m2, $n)" } val resShape = newThis.shape.sliceArray(0..(newThis.shape.size - 2)) + intArrayOf(newOther.shape.last()) @@ -436,9 +436,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { * @param epsilon permissible error when comparing two Double values. * @return true if two tensors have the same shape and elements, false otherwise. */ - public fun Tensor.eq(other: Tensor, epsilon: Double): Boolean { - return tensor.eq(other) { x, y -> abs(x - y) < epsilon } - } + public fun Tensor.eq(other: Tensor, epsilon: Double): Boolean = + tensor.eq(other) { x, y -> abs(x - y) < epsilon } /** * Compares element-wise two tensors. @@ -510,7 +509,7 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { } /** - * Build tensor from rows of input tensor + * Builds tensor from rows of input tensor * * @param indices the [IntArray] of 1-dimensional indices * @return tensor with rows corresponding to rows by [indices] diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt index 68aa03311..f65e2b955 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt @@ -23,7 +23,6 @@ internal fun stridesFromShape(shape: IntArray): IntArray { current-- } return res - } internal fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArray { @@ -55,4 +54,4 @@ public class TensorLinearStructure(override val shape: IntArray) : Strides { override val linearSize: Int get() = shape.reduce(Int::times) -} \ No newline at end of file +} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt index 6254ce751..2743a5218 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt @@ -33,4 +33,4 @@ public fun IntTensor.toIntArray(): IntArray { return IntArray(numElements) { i -> mutableBuffer[bufferStart + i] } -} \ No newline at end of file +} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt index 31de6919f..70e3b9c61 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt @@ -39,4 +39,4 @@ internal val Tensor.tensor: IntTensor get() = when (this) { is IntTensor -> this else -> this.toBufferedTensor().asTensor() - } \ No newline at end of file + } From 0920e21d622e85e95e25b6d28d906309dab8d875 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 12:52:17 +0100 Subject: [PATCH 300/393] Merging implementations together --- .../kmath/tensors/DataSetNormalization.kt | 20 +- .../tensors/LinearSystemSolvingWithLUP.kt | 4 +- .../kscience/kmath/tensors/NeuralNetwork.kt | 26 +- .../kscience/kmath/tensors/OLSWithSVD.kt | 9 +- .../space/kscience/kmath/tensors/PCA.kt | 11 +- .../tensors/api/AnalyticTensorAlgebra.kt | 3 +- .../tensors/api/LinearOpsTensorAlgebra.kt | 3 +- .../api/TensorPartialDivisionAlgebra.kt | 3 +- .../kmath/tensors/core/DoubleTensor.kt | 1 + .../algebras/BroadcastDoubleTensorAlgebra.kt | 6 +- .../algebras/DoubleAnalyticTensorAlgebra.kt | 116 ------ .../algebras/DoubleLinearOpsTensorAlgebra.kt | 278 ------------- .../core/algebras/DoubleTensorAlgebra.kt | 385 +++++++++++++++++- .../core/{ => internal}/broadcastUtils.kt | 8 +- .../tensors/core/{ => internal}/checks.kt | 11 +- .../tensors/core/{ => internal}/linUtils.kt | 27 +- .../core/{ => internal}/tensorCastsUtils.kt | 5 +- .../tensors/core/{ => internal}/utils.kt | 9 +- .../kmath/tensors/core/tensorCasts.kt | 1 + .../kmath/tensors/core/TestBroadcasting.kt | 1 + .../core/TestDoubleAnalyticTensorAlgebra.kt | 31 +- .../core/TestDoubleLinearOpsAlgebra.kt | 30 +- .../kmath/tensors/core/TestDoubleTensor.kt | 4 + .../tensors/core/TestDoubleTensorAlgebra.kt | 1 + 24 files changed, 488 insertions(+), 505 deletions(-) delete mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt delete mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => internal}/broadcastUtils.kt (94%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => internal}/checks.kt (83%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => internal}/linUtils.kt (91%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => internal}/tensorCastsUtils.kt (88%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{ => internal}/utils.kt (91%) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt index 4d53d940b..d029348f2 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt @@ -7,22 +7,22 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra + // Dataset normalization fun main() { - // work in context with analytic methods - DoubleAnalyticTensorAlgebra { + // work in context with broadcast methods + BroadcastDoubleTensorAlgebra { // take dataset of 5-element vectors from normal distribution val dataset = randomNormal(intArrayOf(100, 5)) * 1.5 // all elements from N(0, 1.5) - BroadcastDoubleTensorAlgebra { - dataset += fromArray( - intArrayOf(5), - doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means - ) - } + + dataset += fromArray( + intArrayOf(5), + doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means + ) + // find out mean and standard deviation of each column val mean = dataset.mean(0, false) @@ -36,7 +36,7 @@ fun main() { println("Maximum:\n${dataset.max(0, false)}") // now we can scale dataset with mean normalization - val datasetScaled = BroadcastDoubleTensorAlgebra { (dataset - mean) / std } + val datasetScaled = (dataset - mean) / std // find out mean and std of scaled dataset diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index bd8233ccc..c0ece04ca 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -7,14 +7,14 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra // solving linear system with LUP decomposition fun main () { // work in context with linear operations - DoubleLinearOpsTensorAlgebra { + BroadcastDoubleTensorAlgebra { // set true value of x val trueX = fromArray( diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt index ea863988c..1998b8d16 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt @@ -8,7 +8,6 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.toDoubleArray import kotlin.math.sqrt @@ -48,7 +47,7 @@ fun reluDer(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { // activation layer with relu activator class ReLU : Activation(::relu, ::reluDer) -fun sigmoid(x: DoubleTensor): DoubleTensor = DoubleAnalyticTensorAlgebra { +fun sigmoid(x: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { 1.0 / (1.0 + (-x).exp()) } @@ -83,9 +82,7 @@ class Dense( val gradInput = outputError dot weights.transpose() val gradW = input.transpose() dot outputError - val gradBias = DoubleAnalyticTensorAlgebra { - outputError.mean(dim = 0, keepDim = false) * input.shape[0].toDouble() - } + val gradBias = outputError.mean(dim = 0, keepDim = false) * input.shape[0].toDouble() weights -= learningRate * gradW bias -= learningRate * gradBias @@ -110,7 +107,7 @@ fun accuracy(yPred: DoubleTensor, yTrue: DoubleTensor): Double { // neural network class class NeuralNetwork(private val layers: List) { - private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = DoubleAnalyticTensorAlgebra { + private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra { val onesForAnswers = yPred.zeroesLike() yTrue.toDoubleArray().forEachIndexed { index, labelDouble -> @@ -118,7 +115,7 @@ class NeuralNetwork(private val layers: List) { onesForAnswers[intArrayOf(index, label)] = 1.0 } - val softmaxValue = BroadcastDoubleTensorAlgebra { yPred.exp() / yPred.exp().sum(dim = 1, keepDim = true) } + val softmaxValue = yPred.exp() / yPred.exp().sum(dim = 1, keepDim = true) (-onesForAnswers + softmaxValue) / (yPred.shape[0].toDouble()) } @@ -177,10 +174,9 @@ class NeuralNetwork(private val layers: List) { } - @OptIn(ExperimentalStdlibApi::class) fun main() { - DoubleTensorAlgebra { + BroadcastDoubleTensorAlgebra { val features = 5 val sampleSize = 250 val trainSize = 180 @@ -188,12 +184,12 @@ fun main() { // take sample of features from normal distribution val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5 - BroadcastDoubleTensorAlgebra { - x += fromArray( - intArrayOf(5), - doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means - ) - } + + x += fromArray( + intArrayOf(5), + doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means + ) + // define class like '1' if the sum of features > 0 and '0' otherwise val y = fromArray( diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 435af35f6..497f63b41 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -7,8 +7,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.math.abs @@ -19,7 +18,7 @@ fun main() { val randSeed = 100500L // work in context with linear operations - DoubleLinearOpsTensorAlgebra { + DoubleTensorAlgebra { // take coefficient vector from normal distribution val alpha = randomNormal( intArrayOf(5), @@ -56,12 +55,12 @@ fun main() { "$alphaOLS") // figure out MSE of approximation - fun mse(yTrue: DoubleTensor, yPred: DoubleTensor): Double = DoubleAnalyticTensorAlgebra{ + fun mse(yTrue: DoubleTensor, yPred: DoubleTensor): Double { require(yTrue.shape.size == 1) require(yTrue.shape contentEquals yPred.shape) val diff = yTrue - yPred - diff.dot(diff).sqrt().value() + return diff.dot(diff).sqrt().value() } println("MSE: ${mse(alpha, alphaOLS)}") diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt index ee25b63a3..d29dbb094 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -7,9 +7,6 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra - // simple PCA @@ -17,8 +14,8 @@ import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra fun main(){ val seed = 100500L - // work in context with analytic methods - DoubleAnalyticTensorAlgebra { + // work in context with broadcast methods + BroadcastDoubleTensorAlgebra { // assume x is range from 0 until 10 val x = fromArray( @@ -63,7 +60,7 @@ fun main(){ println("Covariance matrix:\n$covMatrix") // and find out eigenvector of it - val (_, evecs) = DoubleLinearOpsTensorAlgebra {covMatrix.symEig()} + val (_, evecs) = covMatrix.symEig() val v = evecs[0] println("Eigenvector:\n$v") @@ -74,7 +71,7 @@ fun main(){ // we can restore original data from reduced data. // for example, find 7th element of dataset val n = 7 - val restored = BroadcastDoubleTensorAlgebra{(datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean} + val restored = (datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean println("Original value:\n${dataset[n]}") println("Restored value:\n$restored") } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 69e88c28f..1db986e77 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -11,8 +11,7 @@ package space.kscience.kmath.tensors.api * * @param T the type of items closed under analytic functions in the tensors. */ -public interface AnalyticTensorAlgebra : - TensorPartialDivisionAlgebra { +public interface AnalyticTensorAlgebra : TensorPartialDivisionAlgebra { /** * @return the mean of all elements in the input tensor. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 4a325ab4e..6bdecfa85 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -10,8 +10,7 @@ package space.kscience.kmath.tensors.api * * @param T the type of items closed under division in the tensors. */ -public interface LinearOpsTensorAlgebra : - TensorPartialDivisionAlgebra { +public interface LinearOpsTensorAlgebra : TensorPartialDivisionAlgebra { /** * Computes the determinant of a square matrix input, or of each square matrix in a batched input. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt index 921157963..02bf5415d 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt @@ -11,8 +11,7 @@ package space.kscience.kmath.tensors.api * * @param T the type of items closed under division in the tensors. */ -public interface TensorPartialDivisionAlgebra : - TensorAlgebra { +public interface TensorPartialDivisionAlgebra : TensorAlgebra { /** * Each element of the tensor [other] is divided by this value. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt index e3143f5a7..41df50cba 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.tensors.core.internal.toPrettyString /** * Default [BufferedTensor] implementation for [Double] values diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt index 873ec9027..bc7d90c28 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt @@ -7,8 +7,10 @@ package space.kscience.kmath.tensors.core.algebras import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.* -import space.kscience.kmath.tensors.core.broadcastTensors -import space.kscience.kmath.tensors.core.broadcastTo +import space.kscience.kmath.tensors.core.internal.array +import space.kscience.kmath.tensors.core.internal.broadcastTensors +import space.kscience.kmath.tensors.core.internal.broadcastTo +import space.kscience.kmath.tensors.core.internal.tensor /** * Basic linear algebra operations implemented with broadcasting. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt deleted file mode 100644 index 23a2fa282..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleAnalyticTensorAlgebra.kt +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.tensors.core.algebras - -import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra -import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.tensor -import kotlin.math.* - -public object DoubleAnalyticTensorAlgebra : - AnalyticTensorAlgebra, - DoubleTensorAlgebra() { - - override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } - - override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim( - { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - arr.sum() / shape[dim] - }, - dim, - keepDim - ) - - override fun Tensor.std(): Double = this.fold { arr -> - val mean = arr.sum() / tensor.numElements - sqrt(arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1)) - } - - override fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( - { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - val mean = arr.sum() / shape[dim] - sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) - }, - dim, - keepDim - ) - - override fun Tensor.variance(): Double = this.fold { arr -> - val mean = arr.sum() / tensor.numElements - arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1) - } - - override fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( - { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - val mean = arr.sum() / shape[dim] - arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) - }, - dim, - keepDim - ) - - private fun cov(x: DoubleTensor, y:DoubleTensor): Double{ - val n = x.shape[0] - return ((x - x.mean()) * (y - y.mean())).mean() * n / (n - 1) - } - - override fun cov(tensors: List>): DoubleTensor { - check(tensors.isNotEmpty()) { "List must have at least 1 element" } - val n = tensors.size - val m = tensors[0].shape[0] - check(tensors.all { it.shape contentEquals intArrayOf(m) }) { "Tensors must have same shapes" } - val resTensor = DoubleTensor( - intArrayOf(n, n), - DoubleArray(n * n) {0.0} - ) - for (i in 0 until n){ - for (j in 0 until n){ - resTensor[intArrayOf(i, j)] = cov(tensors[i].tensor, tensors[j].tensor) - } - } - return resTensor - } - - override fun Tensor.exp(): DoubleTensor = tensor.map(::exp) - - override fun Tensor.ln(): DoubleTensor = tensor.map(::ln) - - override fun Tensor.sqrt(): DoubleTensor = tensor.map(::sqrt) - - override fun Tensor.cos(): DoubleTensor = tensor.map(::cos) - - override fun Tensor.acos(): DoubleTensor = tensor.map(::acos) - - override fun Tensor.cosh(): DoubleTensor = tensor.map(::cosh) - - override fun Tensor.acosh(): DoubleTensor = tensor.map(::acosh) - - override fun Tensor.sin(): DoubleTensor = tensor.map(::sin) - - override fun Tensor.asin(): DoubleTensor = tensor.map(::asin) - - override fun Tensor.sinh(): DoubleTensor = tensor.map(::sinh) - - override fun Tensor.asinh(): DoubleTensor = tensor.map(::asinh) - - override fun Tensor.tan(): DoubleTensor = tensor.map(::tan) - - override fun Tensor.atan(): DoubleTensor = tensor.map(::atan) - - override fun Tensor.tanh(): DoubleTensor = tensor.map(::tanh) - - override fun Tensor.atanh(): DoubleTensor = tensor.map(::atanh) - - override fun Tensor.ceil(): DoubleTensor = tensor.map(::ceil) - - override fun Tensor.floor(): DoubleTensor = tensor.map(::floor) - -} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt deleted file mode 100644 index 430482613..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.tensors.core.algebras - -import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra -import space.kscience.kmath.nd.as1D -import space.kscience.kmath.nd.as2D -import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.* -import space.kscience.kmath.tensors.core.checkSquareMatrix -import space.kscience.kmath.tensors.core.choleskyHelper -import space.kscience.kmath.tensors.core.cleanSymHelper -import space.kscience.kmath.tensors.core.luHelper -import space.kscience.kmath.tensors.core.luMatrixDet -import space.kscience.kmath.tensors.core.luMatrixInv -import space.kscience.kmath.tensors.core.luPivotHelper -import space.kscience.kmath.tensors.core.pivInit -import kotlin.math.min - -/** - * Implementation of common linear algebra operations on double numbers. - * Implements the LinearOpsTensorAlgebra interface. - */ -public object DoubleLinearOpsTensorAlgebra : - LinearOpsTensorAlgebra, - DoubleTensorAlgebra() { - - override fun Tensor.inv(): DoubleTensor = invLU(1e-9) - - override fun Tensor.det(): DoubleTensor = detLU(1e-9) - - /** - * Computes the LU factorization of a matrix or batches of matrices `input`. - * Returns a tuple containing the LU factorization and pivots of `input`. - * - * @param epsilon permissible error when comparing the determinant of a matrix with zero - * @return pair of `factorization` and `pivots`. - * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. - * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. - */ - public fun Tensor.luFactor(epsilon: Double): Pair = - computeLU(tensor, epsilon) - ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") - - /** - * Computes the LU factorization of a matrix or batches of matrices `input`. - * Returns a tuple containing the LU factorization and pivots of `input`. - * Uses an error of ``1e-9`` when calculating whether a matrix is degenerate. - * - * @return pair of `factorization` and `pivots`. - * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. - * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. - */ - public fun Tensor.luFactor(): Pair = luFactor(1e-9) - - /** - * Unpacks the data and pivots from a LU factorization of a tensor. - * Given a tensor [luTensor], return tensors (P, L, U) satisfying ``P * luTensor = L * U``, - * with `P` being a permutation matrix or batch of matrices, - * `L` being a lower triangular matrix or batch of matrices, - * `U` being an upper triangular matrix or batch of matrices. - * - * @param luTensor the packed LU factorization data - * @param pivotsTensor the packed LU factorization pivots - * @return triple of P, L and U tensors - */ - public fun luPivot( - luTensor: Tensor, - pivotsTensor: Tensor - ): Triple { - checkSquareMatrix(luTensor.shape) - check( - luTensor.shape.dropLast(2).toIntArray() contentEquals pivotsTensor.shape.dropLast(1).toIntArray() || - luTensor.shape.last() == pivotsTensor.shape.last() - 1 - ) { "Inappropriate shapes of input tensors" } - - val n = luTensor.shape.last() - val pTensor = luTensor.zeroesLike() - pTensor - .matrixSequence() - .zip(pivotsTensor.tensor.vectorSequence()) - .forEach { (p, pivot) -> pivInit(p.as2D(), pivot.as1D(), n) } - - val lTensor = luTensor.zeroesLike() - val uTensor = luTensor.zeroesLike() - - lTensor.matrixSequence() - .zip(uTensor.matrixSequence()) - .zip(luTensor.tensor.matrixSequence()) - .forEach { (pairLU, lu) -> - val (l, u) = pairLU - luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) - } - - return Triple(pTensor, lTensor, uTensor) - } - - /** - * QR decomposition. - * - * Computes the QR decomposition of a matrix or a batch of matrices, and returns a pair `(Q, R)` of tensors. - * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q * R``, - * with `Q` being an orthogonal matrix or batch of orthogonal matrices - * and `R` being an upper triangular matrix or batch of upper triangular matrices. - * - * @param epsilon permissible error when comparing tensors for equality. - * Used when checking the positive definiteness of the input matrix or matrices. - * @return pair of Q and R tensors. - */ - public fun Tensor.cholesky(epsilon: Double): DoubleTensor { - checkSquareMatrix(shape) - checkPositiveDefinite(tensor, epsilon) - - val n = shape.last() - val lTensor = zeroesLike() - - for ((a, l) in tensor.matrixSequence().zip(lTensor.matrixSequence())) - for (i in 0 until n) choleskyHelper(a.as2D(), l.as2D(), n) - - return lTensor - } - - override fun Tensor.cholesky(): DoubleTensor = cholesky(1e-6) - - override fun Tensor.qr(): Pair { - checkSquareMatrix(shape) - val qTensor = zeroesLike() - val rTensor = zeroesLike() - tensor.matrixSequence() - .zip((qTensor.matrixSequence() - .zip(rTensor.matrixSequence()))).forEach { (matrix, qr) -> - val (q, r) = qr - qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) - } - - return qTensor to rTensor - } - - override fun Tensor.svd(): Triple = - svd(epsilon = 1e-10) - - /** - * Singular Value Decomposition. - * - * Computes the singular value decomposition of either a matrix or batch of matrices `input`. - * The singular value decomposition is represented as a triple `(U, S, V)`, - * such that ``input = U.dot(diagonalEmbedding(S).dot(V.T))``. - * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. - * - * @param epsilon permissible error when calculating the dot product of vectors, - * i.e. the precision with which the cosine approaches 1 in an iterative algorithm. - * @return triple `(U, S, V)`. - */ - public fun Tensor.svd(epsilon: Double): Triple { - val size = tensor.dimension - val commonShape = tensor.shape.sliceArray(0 until size - 2) - val (n, m) = tensor.shape.sliceArray(size - 2 until size) - val uTensor = zeros(commonShape + intArrayOf(min(n, m), n)) - val sTensor = zeros(commonShape + intArrayOf(min(n, m))) - val vTensor = zeros(commonShape + intArrayOf(min(n, m), m)) - - tensor.matrixSequence() - .zip(uTensor.matrixSequence() - .zip(sTensor.vectorSequence() - .zip(vTensor.matrixSequence()))).forEach { (matrix, USV) -> - val matrixSize = matrix.shape.reduce { acc, i -> acc * i } - val curMatrix = DoubleTensor( - matrix.shape, - matrix.mutableBuffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize) - .toDoubleArray() - ) - svdHelper(curMatrix, USV, m, n, epsilon) - } - - return Triple(uTensor.transpose(), sTensor, vTensor.transpose()) - } - - override fun Tensor.symEig(): Pair = - symEig(epsilon = 1e-15) - - /** - * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, - * represented by a pair (eigenvalues, eigenvectors). - * - * @param epsilon permissible error when comparing tensors for equality - * and when the cosine approaches 1 in the SVD algorithm. - * @return a pair (eigenvalues, eigenvectors) - */ - public fun Tensor.symEig(epsilon: Double): Pair { - checkSymmetric(tensor, epsilon) - val (u, s, v) = tensor.svd(epsilon) - val shp = s.shape + intArrayOf(1) - val utv = u.transpose() dot v - val n = s.shape.last() - for (matrix in utv.matrixSequence()) - cleanSymHelper(matrix.as2D(), n) - - val eig = (utv dot s.view(shp)).view(s.shape) - return eig to v - } - - /** - * Computes the determinant of a square matrix input, or of each square matrix in a batched input - * using LU factorization algorithm. - * - * @param epsilon error in the LU algorithm - permissible error when comparing the determinant of a matrix with zero - * @return the determinant. - */ - public fun Tensor.detLU(epsilon: Double = 1e-9): DoubleTensor { - - checkSquareMatrix(tensor.shape) - val luTensor = tensor.copy() - val pivotsTensor = tensor.setUpPivots() - - val n = shape.size - - val detTensorShape = IntArray(n - 1) { i -> shape[i] } - detTensorShape[n - 2] = 1 - val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } - - val detTensor = DoubleTensor( - detTensorShape, - resBuffer - ) - - luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (lu, pivots) -> - resBuffer[index] = if (luHelper(lu.as2D(), pivots.as1D(), epsilon)) - 0.0 else luMatrixDet(lu.as2D(), pivots.as1D()) - } - - return detTensor - } - - /** - * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input - * using LU factorization algorithm. - * Given a square matrix `a`, return the matrix `aInv` satisfying - * ``a.dot(aInv) = aInv.dot(a) = eye(a.shape[0])``. - * - * @param epsilon error in the LU algorithm - permissible error when comparing the determinant of a matrix with zero - * @return the multiplicative inverse of a matrix. - */ - public fun Tensor.invLU(epsilon: Double = 1e-9): DoubleTensor { - val (luTensor, pivotsTensor) = luFactor(epsilon) - val invTensor = luTensor.zeroesLike() - - val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) - for ((luP, invMatrix) in seq) { - val (lu, pivots) = luP - luMatrixInv(lu.as2D(), pivots.as1D(), invMatrix.as2D()) - } - - return invTensor - } - - /** - * LUP decomposition - * - * Computes the LUP decomposition of a matrix or a batch of matrices. - * Given a tensor `input`, return tensors (P, L, U) satisfying ``P * input = L * U``, - * with `P` being a permutation matrix or batch of matrices, - * `L` being a lower triangular matrix or batch of matrices, - * `U` being an upper triangular matrix or batch of matrices. - * - * @param epsilon permissible error when comparing the determinant of a matrix with zero - * @return triple of P, L and U tensors - */ - public fun Tensor.lu(epsilon: Double = 1e-9): Triple { - val (lu, pivots) = this.luFactor(epsilon) - return luPivot(lu, pivots) - } - - override fun Tensor.lu(): Triple = lu(1e-9) - -} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt index e5d41f856..cb06432d0 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt @@ -5,28 +5,34 @@ package space.kscience.kmath.tensors.core.algebras +import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D +import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra +import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.* -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.fold -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra.foldDim -import space.kscience.kmath.tensors.core.broadcastOuterTensors -import space.kscience.kmath.tensors.core.checkBufferShapeConsistency -import space.kscience.kmath.tensors.core.checkEmptyDoubleBuffer -import space.kscience.kmath.tensors.core.checkEmptyShape -import space.kscience.kmath.tensors.core.checkShapesCompatible -import space.kscience.kmath.tensors.core.checkTranspose -import space.kscience.kmath.tensors.core.checkView -import space.kscience.kmath.tensors.core.dotHelper -import space.kscience.kmath.tensors.core.getRandomNormals -import space.kscience.kmath.tensors.core.minusIndexFrom -import kotlin.math.abs +import space.kscience.kmath.tensors.core.internal.dotHelper +import space.kscience.kmath.tensors.core.internal.getRandomNormals +import space.kscience.kmath.tensors.core.internal.* +import space.kscience.kmath.tensors.core.internal.broadcastOuterTensors +import space.kscience.kmath.tensors.core.internal.checkBufferShapeConsistency +import space.kscience.kmath.tensors.core.internal.checkEmptyDoubleBuffer +import space.kscience.kmath.tensors.core.internal.checkEmptyShape +import space.kscience.kmath.tensors.core.internal.checkShapesCompatible +import space.kscience.kmath.tensors.core.internal.checkSquareMatrix +import space.kscience.kmath.tensors.core.internal.checkTranspose +import space.kscience.kmath.tensors.core.internal.checkView +import space.kscience.kmath.tensors.core.internal.minusIndexFrom +import kotlin.math.* /** * Implementation of basic operations over double tensors and basic algebra operations on them. */ -public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { +public open class DoubleTensorAlgebra : + TensorPartialDivisionAlgebra, + AnalyticTensorAlgebra, + LinearOpsTensorAlgebra { public companion object : DoubleTensorAlgebra() @@ -311,9 +317,8 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { return DoubleTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart) } - override fun Tensor.viewAs(other: Tensor): DoubleTensor { - return tensor.view(other.shape) - } + override fun Tensor.viewAs(other: Tensor): DoubleTensor = + tensor.view(other.shape) override infix fun Tensor.dot(other: Tensor): DoubleTensor { if (tensor.shape.size == 1 && other.shape.size == 1) { @@ -565,4 +570,350 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra { x.withIndex().maxByOrNull { it.value }?.index!!.toDouble() }, dim, keepDim) + + override fun Tensor.mean(): Double = this.fold { it.sum() / tensor.numElements } + + override fun Tensor.mean(dim: Int, keepDim: Boolean): DoubleTensor = + foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + arr.sum() / shape[dim] + }, + dim, + keepDim + ) + + override fun Tensor.std(): Double = this.fold { arr -> + val mean = arr.sum() / tensor.numElements + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1)) + } + + override fun Tensor.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val mean = arr.sum() / shape[dim] + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) + }, + dim, + keepDim + ) + + override fun Tensor.variance(): Double = this.fold { arr -> + val mean = arr.sum() / tensor.numElements + arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1) + } + + override fun Tensor.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val mean = arr.sum() / shape[dim] + arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) + }, + dim, + keepDim + ) + + private fun cov(x: DoubleTensor, y:DoubleTensor): Double{ + val n = x.shape[0] + return ((x - x.mean()) * (y - y.mean())).mean() * n / (n - 1) + } + + override fun cov(tensors: List>): DoubleTensor { + check(tensors.isNotEmpty()) { "List must have at least 1 element" } + val n = tensors.size + val m = tensors[0].shape[0] + check(tensors.all { it.shape contentEquals intArrayOf(m) }) { "Tensors must have same shapes" } + val resTensor = DoubleTensor( + intArrayOf(n, n), + DoubleArray(n * n) {0.0} + ) + for (i in 0 until n){ + for (j in 0 until n){ + resTensor[intArrayOf(i, j)] = cov(tensors[i].tensor, tensors[j].tensor) + } + } + return resTensor + } + + override fun Tensor.exp(): DoubleTensor = tensor.map(::exp) + + override fun Tensor.ln(): DoubleTensor = tensor.map(::ln) + + override fun Tensor.sqrt(): DoubleTensor = tensor.map(::sqrt) + + override fun Tensor.cos(): DoubleTensor = tensor.map(::cos) + + override fun Tensor.acos(): DoubleTensor = tensor.map(::acos) + + override fun Tensor.cosh(): DoubleTensor = tensor.map(::cosh) + + override fun Tensor.acosh(): DoubleTensor = tensor.map(::acosh) + + override fun Tensor.sin(): DoubleTensor = tensor.map(::sin) + + override fun Tensor.asin(): DoubleTensor = tensor.map(::asin) + + override fun Tensor.sinh(): DoubleTensor = tensor.map(::sinh) + + override fun Tensor.asinh(): DoubleTensor = tensor.map(::asinh) + + override fun Tensor.tan(): DoubleTensor = tensor.map(::tan) + + override fun Tensor.atan(): DoubleTensor = tensor.map(::atan) + + override fun Tensor.tanh(): DoubleTensor = tensor.map(::tanh) + + override fun Tensor.atanh(): DoubleTensor = tensor.map(::atanh) + + override fun Tensor.ceil(): DoubleTensor = tensor.map(::ceil) + + override fun Tensor.floor(): DoubleTensor = tensor.map(::floor) + + override fun Tensor.inv(): DoubleTensor = invLU(1e-9) + + override fun Tensor.det(): DoubleTensor = detLU(1e-9) + + /** + * Computes the LU factorization of a matrix or batches of matrices `input`. + * Returns a tuple containing the LU factorization and pivots of `input`. + * + * @param epsilon permissible error when comparing the determinant of a matrix with zero + * @return pair of `factorization` and `pivots`. + * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. + * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. + */ + public fun Tensor.luFactor(epsilon: Double): Pair = + computeLU(tensor, epsilon) + ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") + + /** + * Computes the LU factorization of a matrix or batches of matrices `input`. + * Returns a tuple containing the LU factorization and pivots of `input`. + * Uses an error of ``1e-9`` when calculating whether a matrix is degenerate. + * + * @return pair of `factorization` and `pivots`. + * The `factorization` has the shape ``(*, m, n)``, where``(*, m, n)`` is the shape of the `input` tensor. + * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. + */ + public fun Tensor.luFactor(): Pair = luFactor(1e-9) + + /** + * Unpacks the data and pivots from a LU factorization of a tensor. + * Given a tensor [luTensor], return tensors (P, L, U) satisfying ``P * luTensor = L * U``, + * with `P` being a permutation matrix or batch of matrices, + * `L` being a lower triangular matrix or batch of matrices, + * `U` being an upper triangular matrix or batch of matrices. + * + * @param luTensor the packed LU factorization data + * @param pivotsTensor the packed LU factorization pivots + * @return triple of P, L and U tensors + */ + public fun luPivot( + luTensor: Tensor, + pivotsTensor: Tensor + ): Triple { + checkSquareMatrix(luTensor.shape) + check( + luTensor.shape.dropLast(2).toIntArray() contentEquals pivotsTensor.shape.dropLast(1).toIntArray() || + luTensor.shape.last() == pivotsTensor.shape.last() - 1 + ) { "Inappropriate shapes of input tensors" } + + val n = luTensor.shape.last() + val pTensor = luTensor.zeroesLike() + pTensor + .matrixSequence() + .zip(pivotsTensor.tensor.vectorSequence()) + .forEach { (p, pivot) -> pivInit(p.as2D(), pivot.as1D(), n) } + + val lTensor = luTensor.zeroesLike() + val uTensor = luTensor.zeroesLike() + + lTensor.matrixSequence() + .zip(uTensor.matrixSequence()) + .zip(luTensor.tensor.matrixSequence()) + .forEach { (pairLU, lu) -> + val (l, u) = pairLU + luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) + } + + return Triple(pTensor, lTensor, uTensor) + } + + /** + * QR decomposition. + * + * Computes the QR decomposition of a matrix or a batch of matrices, and returns a pair `(Q, R)` of tensors. + * Given a tensor `input`, return tensors (Q, R) satisfying ``input = Q * R``, + * with `Q` being an orthogonal matrix or batch of orthogonal matrices + * and `R` being an upper triangular matrix or batch of upper triangular matrices. + * + * @param epsilon permissible error when comparing tensors for equality. + * Used when checking the positive definiteness of the input matrix or matrices. + * @return pair of Q and R tensors. + */ + public fun Tensor.cholesky(epsilon: Double): DoubleTensor { + checkSquareMatrix(shape) + checkPositiveDefinite(tensor, epsilon) + + val n = shape.last() + val lTensor = zeroesLike() + + for ((a, l) in tensor.matrixSequence().zip(lTensor.matrixSequence())) + for (i in 0 until n) choleskyHelper(a.as2D(), l.as2D(), n) + + return lTensor + } + + override fun Tensor.cholesky(): DoubleTensor = cholesky(1e-6) + + override fun Tensor.qr(): Pair { + checkSquareMatrix(shape) + val qTensor = zeroesLike() + val rTensor = zeroesLike() + tensor.matrixSequence() + .zip((qTensor.matrixSequence() + .zip(rTensor.matrixSequence()))).forEach { (matrix, qr) -> + val (q, r) = qr + qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) + } + + return qTensor to rTensor + } + + override fun Tensor.svd(): Triple = + svd(epsilon = 1e-10) + + /** + * Singular Value Decomposition. + * + * Computes the singular value decomposition of either a matrix or batch of matrices `input`. + * The singular value decomposition is represented as a triple `(U, S, V)`, + * such that ``input = U.dot(diagonalEmbedding(S).dot(V.T))``. + * If input is a batch of tensors, then U, S, and Vh are also batched with the same batch dimensions as input. + * + * @param epsilon permissible error when calculating the dot product of vectors, + * i.e. the precision with which the cosine approaches 1 in an iterative algorithm. + * @return triple `(U, S, V)`. + */ + public fun Tensor.svd(epsilon: Double): Triple { + val size = tensor.dimension + val commonShape = tensor.shape.sliceArray(0 until size - 2) + val (n, m) = tensor.shape.sliceArray(size - 2 until size) + val uTensor = zeros(commonShape + intArrayOf(min(n, m), n)) + val sTensor = zeros(commonShape + intArrayOf(min(n, m))) + val vTensor = zeros(commonShape + intArrayOf(min(n, m), m)) + + tensor.matrixSequence() + .zip(uTensor.matrixSequence() + .zip(sTensor.vectorSequence() + .zip(vTensor.matrixSequence()))).forEach { (matrix, USV) -> + val matrixSize = matrix.shape.reduce { acc, i -> acc * i } + val curMatrix = DoubleTensor( + matrix.shape, + matrix.mutableBuffer.array().slice(matrix.bufferStart until matrix.bufferStart + matrixSize) + .toDoubleArray() + ) + svdHelper(curMatrix, USV, m, n, epsilon) + } + + return Triple(uTensor.transpose(), sTensor, vTensor.transpose()) + } + + override fun Tensor.symEig(): Pair = + symEig(epsilon = 1e-15) + + /** + * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, + * represented by a pair (eigenvalues, eigenvectors). + * + * @param epsilon permissible error when comparing tensors for equality + * and when the cosine approaches 1 in the SVD algorithm. + * @return a pair (eigenvalues, eigenvectors) + */ + public fun Tensor.symEig(epsilon: Double): Pair { + checkSymmetric(tensor, epsilon) + val (u, s, v) = tensor.svd(epsilon) + val shp = s.shape + intArrayOf(1) + val utv = u.transpose() dot v + val n = s.shape.last() + for (matrix in utv.matrixSequence()) + cleanSymHelper(matrix.as2D(), n) + + val eig = (utv dot s.view(shp)).view(s.shape) + return eig to v + } + + /** + * Computes the determinant of a square matrix input, or of each square matrix in a batched input + * using LU factorization algorithm. + * + * @param epsilon error in the LU algorithm - permissible error when comparing the determinant of a matrix with zero + * @return the determinant. + */ + public fun Tensor.detLU(epsilon: Double = 1e-9): DoubleTensor { + + checkSquareMatrix(tensor.shape) + val luTensor = tensor.copy() + val pivotsTensor = tensor.setUpPivots() + + val n = shape.size + + val detTensorShape = IntArray(n - 1) { i -> shape[i] } + detTensorShape[n - 2] = 1 + val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } + + val detTensor = DoubleTensor( + detTensorShape, + resBuffer + ) + + luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).forEachIndexed { index, (lu, pivots) -> + resBuffer[index] = if (luHelper(lu.as2D(), pivots.as1D(), epsilon)) + 0.0 else luMatrixDet(lu.as2D(), pivots.as1D()) + } + + return detTensor + } + + /** + * Computes the multiplicative inverse matrix of a square matrix input, or of each square matrix in a batched input + * using LU factorization algorithm. + * Given a square matrix `a`, return the matrix `aInv` satisfying + * ``a.dot(aInv) = aInv.dot(a) = eye(a.shape[0])``. + * + * @param epsilon error in the LU algorithm - permissible error when comparing the determinant of a matrix with zero + * @return the multiplicative inverse of a matrix. + */ + public fun Tensor.invLU(epsilon: Double = 1e-9): DoubleTensor { + val (luTensor, pivotsTensor) = luFactor(epsilon) + val invTensor = luTensor.zeroesLike() + + val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) + for ((luP, invMatrix) in seq) { + val (lu, pivots) = luP + luMatrixInv(lu.as2D(), pivots.as1D(), invMatrix.as2D()) + } + + return invTensor + } + + /** + * LUP decomposition + * + * Computes the LUP decomposition of a matrix or a batch of matrices. + * Given a tensor `input`, return tensors (P, L, U) satisfying ``P * input = L * U``, + * with `P` being a permutation matrix or batch of matrices, + * `L` being a lower triangular matrix or batch of matrices, + * `U` being an upper triangular matrix or batch of matrices. + * + * @param epsilon permissible error when comparing the determinant of a matrix with zero + * @return triple of P, L and U tensors + */ + public fun Tensor.lu(epsilon: Double = 1e-9): Triple { + val (lu, pivots) = this.luFactor(epsilon) + return luPivot(lu, pivots) + } + + override fun Tensor.lu(): Triple = lu(1e-9) + } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt similarity index 94% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt index dfac054b5..6324dc242 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt @@ -1,5 +1,11 @@ -package space.kscience.kmath.tensors.core +/* + * 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.tensors.core.internal + +import space.kscience.kmath.tensors.core.DoubleTensor import kotlin.math.max internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt similarity index 83% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt index f8bd5027a..0221c961e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt @@ -1,7 +1,12 @@ -package space.kscience.kmath.tensors.core +/* + * 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.tensors.core.internal import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra @@ -50,7 +55,7 @@ internal fun DoubleTensorAlgebra.checkSymmetric( "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" } -internal fun DoubleLinearOpsTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { +internal fun DoubleTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { checkSymmetric(tensor, epsilon) for (mat in tensor.matrixSequence()) check(mat.asTensor().detLU().value() > 0.0) { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt similarity index 91% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt index 8adbfad39..23909f81e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt @@ -1,12 +1,17 @@ -package space.kscience.kmath.tensors.core +/* + * 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.tensors.core.internal import space.kscience.kmath.nd.MutableStructure1D import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra +import space.kscience.kmath.tensors.core.* +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.math.abs import kotlin.math.min import kotlin.math.sign @@ -114,7 +119,7 @@ internal fun BufferedTensor.setUpPivots(): IntTensor { ) } -internal fun DoubleLinearOpsTensorAlgebra.computeLU( +internal fun DoubleTensorAlgebra.computeLU( tensor: DoubleTensor, epsilon: Double ): Pair? { @@ -218,7 +223,7 @@ internal fun luMatrixInv( } } -internal fun DoubleLinearOpsTensorAlgebra.qrHelper( +internal fun DoubleTensorAlgebra.qrHelper( matrix: DoubleTensor, q: DoubleTensor, r: MutableStructure2D @@ -241,14 +246,14 @@ internal fun DoubleLinearOpsTensorAlgebra.qrHelper( } } } - r[j, j] = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + r[j, j] = DoubleTensorAlgebra { (v dot v).sqrt().value() } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } } } -internal fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { +internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10): DoubleTensor { val (n, m) = a.shape var v: DoubleTensor val b: DoubleTensor @@ -264,7 +269,7 @@ internal fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double while (true) { lastV = v v = b.dot(lastV) - val norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + val norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } v = v.times(1.0 / norm) if (abs(v.dot(lastV).value()) > 1 - epsilon) { return v @@ -272,7 +277,7 @@ internal fun DoubleLinearOpsTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double } } -internal fun DoubleLinearOpsTensorAlgebra.svdHelper( +internal fun DoubleTensorAlgebra.svdHelper( matrix: DoubleTensor, USV: Pair, Pair, BufferedTensor>>, m: Int, n: Int, epsilon: Double @@ -298,12 +303,12 @@ internal fun DoubleLinearOpsTensorAlgebra.svdHelper( if (n > m) { v = svd1d(a, epsilon) u = matrix.dot(v) - norm = DoubleAnalyticTensorAlgebra { (u dot u).sqrt().value() } + norm = DoubleTensorAlgebra { (u dot u).sqrt().value() } u = u.times(1.0 / norm) } else { u = svd1d(a, epsilon) v = matrix.transpose(0, 1).dot(u) - norm = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() } + norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } v = v.times(1.0 / norm) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt similarity index 88% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt index 70e3b9c61..67cb0b842 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCastsUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt @@ -3,11 +3,14 @@ * 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.tensors.core +package space.kscience.kmath.tensors.core.internal import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.structures.asMutableBuffer import space.kscience.kmath.tensors.api.Tensor +import space.kscience.kmath.tensors.core.BufferedTensor +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.IntTensor import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure internal fun BufferedTensor.asTensor(): IntTensor = diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt similarity index 91% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt index 0211342bb..0ffaf39e7 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt @@ -1,9 +1,16 @@ -package space.kscience.kmath.tensors.core +/* + * 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.tensors.core.internal import space.kscience.kmath.nd.as1D import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator import space.kscience.kmath.structures.* +import space.kscience.kmath.tensors.core.BufferedTensor +import space.kscience.kmath.tensors.core.DoubleTensor import kotlin.math.* /** diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt index 2743a5218..814a1bb9b 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.api.Tensor +import space.kscience.kmath.tensors.core.internal.tensor /** * Casts [Tensor] to [DoubleTensor] diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 6e3b4df60..80c7ab13a 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -3,6 +3,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.internal.* import kotlin.test.Test import kotlin.test.assertTrue diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 3ea19da26..4dcc367ca 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -1,7 +1,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.math.* import kotlin.test.Test @@ -28,73 +27,73 @@ internal class TestDoubleAnalyticTensorAlgebra { } @Test - fun testExp() = DoubleAnalyticTensorAlgebra { + fun testExp() = DoubleTensorAlgebra { assertTrue { tensor.exp() eq expectedTensor(::exp) } } @Test - fun testLog() = DoubleAnalyticTensorAlgebra { + fun testLog() = DoubleTensorAlgebra { assertTrue { tensor.ln() eq expectedTensor(::ln) } } @Test - fun testSqrt() = DoubleAnalyticTensorAlgebra { + fun testSqrt() = DoubleTensorAlgebra { assertTrue { tensor.sqrt() eq expectedTensor(::sqrt) } } @Test - fun testCos() = DoubleAnalyticTensorAlgebra { + fun testCos() = DoubleTensorAlgebra { assertTrue { tensor.cos() eq expectedTensor(::cos) } } @Test - fun testCosh() = DoubleAnalyticTensorAlgebra { + fun testCosh() = DoubleTensorAlgebra { assertTrue { tensor.cosh() eq expectedTensor(::cosh) } } @Test - fun testAcosh() = DoubleAnalyticTensorAlgebra { + fun testAcosh() = DoubleTensorAlgebra { assertTrue { tensor.acosh() eq expectedTensor(::acosh) } } @Test - fun testSin() = DoubleAnalyticTensorAlgebra { + fun testSin() = DoubleTensorAlgebra { assertTrue { tensor.sin() eq expectedTensor(::sin) } } @Test - fun testSinh() = DoubleAnalyticTensorAlgebra { + fun testSinh() = DoubleTensorAlgebra { assertTrue { tensor.sinh() eq expectedTensor(::sinh) } } @Test - fun testAsinh() = DoubleAnalyticTensorAlgebra { + fun testAsinh() = DoubleTensorAlgebra { assertTrue { tensor.asinh() eq expectedTensor(::asinh) } } @Test - fun testTan() = DoubleAnalyticTensorAlgebra { + fun testTan() = DoubleTensorAlgebra { assertTrue { tensor.tan() eq expectedTensor(::tan) } } @Test - fun testAtan() = DoubleAnalyticTensorAlgebra { + fun testAtan() = DoubleTensorAlgebra { assertTrue { tensor.atan() eq expectedTensor(::atan) } } @Test - fun testTanh() = DoubleAnalyticTensorAlgebra { + fun testTanh() = DoubleTensorAlgebra { assertTrue { tensor.tanh() eq expectedTensor(::tanh) } } @Test - fun testCeil() = DoubleAnalyticTensorAlgebra { + fun testCeil() = DoubleTensorAlgebra { assertTrue { tensor.ceil() eq expectedTensor(::ceil) } } @Test - fun testFloor() = DoubleAnalyticTensorAlgebra { + fun testFloor() = DoubleTensorAlgebra { assertTrue { tensor.floor() eq expectedTensor(::floor) } } @@ -145,7 +144,7 @@ internal class TestDoubleAnalyticTensorAlgebra { } @Test - fun testMean() = DoubleAnalyticTensorAlgebra { + fun testMean() = DoubleTensorAlgebra { assertTrue { tensor2.mean() == 1.0 } assertTrue { tensor2.mean(0, true) eq fromArray( intArrayOf(1, 2), diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 65070af7f..77748b15e 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -1,7 +1,9 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra +import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.internal.array +import space.kscience.kmath.tensors.core.internal.svd1d import kotlin.math.abs import kotlin.test.Test import kotlin.test.assertEquals @@ -10,7 +12,7 @@ import kotlin.test.assertTrue internal class TestDoubleLinearOpsTensorAlgebra { @Test - fun testDetLU() = DoubleLinearOpsTensorAlgebra { + fun testDetLU() = DoubleTensorAlgebra { val tensor = fromArray( intArrayOf(2, 2, 2), doubleArrayOf( @@ -35,7 +37,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testDet() = DoubleLinearOpsTensorAlgebra { + fun testDet() = DoubleTensorAlgebra { val expectedValue = 0.019827417 val m = fromArray( intArrayOf(3, 3), doubleArrayOf( @@ -49,7 +51,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testDetSingle() = DoubleLinearOpsTensorAlgebra { + fun testDetSingle() = DoubleTensorAlgebra { val expectedValue = 48.151623 val m = fromArray( intArrayOf(1, 1), doubleArrayOf( @@ -61,7 +63,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testInvLU() = DoubleLinearOpsTensorAlgebra { + fun testInvLU() = DoubleTensorAlgebra { val tensor = fromArray( intArrayOf(2, 2, 2), doubleArrayOf( @@ -86,14 +88,14 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testScalarProduct() = DoubleLinearOpsTensorAlgebra { + fun testScalarProduct() = DoubleTensorAlgebra { val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) assertEquals(a.dot(b).value(), 59.92) } @Test - fun testQR() = DoubleLinearOpsTensorAlgebra { + fun testQR() = DoubleTensorAlgebra { val shape = intArrayOf(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, @@ -114,7 +116,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testLU() = DoubleLinearOpsTensorAlgebra { + fun testLU() = DoubleTensorAlgebra { val shape = intArrayOf(2, 2, 2) val buffer = doubleArrayOf( 1.0, 3.0, @@ -134,7 +136,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testCholesky() = DoubleLinearOpsTensorAlgebra { + fun testCholesky() = DoubleTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 5), 0) val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) @@ -145,7 +147,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testSVD1D() = DoubleLinearOpsTensorAlgebra { + fun testSVD1D() = DoubleTensorAlgebra { val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val res = svd1d(tensor2) @@ -156,13 +158,13 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testSVD() = DoubleLinearOpsTensorAlgebra{ + fun testSVD() = DoubleTensorAlgebra{ testSVDFor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } @Test - fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra { + fun testBatchedSVD() = DoubleTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) @@ -170,7 +172,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } @Test - fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra { + fun testBatchedSymEig() = DoubleTensorAlgebra { val tensor = randomNormal(shape = intArrayOf(2, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() @@ -182,7 +184,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { } -private fun DoubleLinearOpsTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10): Unit { +private fun DoubleTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double = 1e-10): Unit { val svd = tensor.svd() val tensorSVD = svd.first diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 132735cc7..c4f9f94b0 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -8,6 +8,10 @@ import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.toDoubleArray import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.internal.array +import space.kscience.kmath.tensors.core.internal.asTensor +import space.kscience.kmath.tensors.core.internal.matrixSequence +import space.kscience.kmath.tensors.core.internal.toBufferedTensor import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index d782d78d9..ed858259e 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -3,6 +3,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.internal.array import kotlin.test.Test import kotlin.test.assertFalse import kotlin.test.assertTrue From 0ef64130aeae0deb5543b9c6f73af3a46f465394 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 13:00:30 +0100 Subject: [PATCH 301/393] TensorLinearStructure made internal --- .../space/kscience/kmath/tensors/DataSetNormalization.kt | 2 +- .../kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt | 2 +- .../kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt | 4 ++-- .../main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt | 2 +- examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt | 2 +- .../core/{algebras => }/BroadcastDoubleTensorAlgebra.kt | 3 +-- .../space/kscience/kmath/tensors/core/BufferedTensor.kt | 5 +++-- .../kmath/tensors/core/{algebras => }/DoubleTensorAlgebra.kt | 3 +-- .../core/{algebras => internal}/TensorLinearStructure.kt | 4 ++-- .../space/kscience/kmath/tensors/core/internal/checks.kt | 2 +- .../space/kscience/kmath/tensors/core/internal/linUtils.kt | 2 +- .../kscience/kmath/tensors/core/internal/tensorCastsUtils.kt | 1 - .../space/kscience/kmath/tensors/core/TestBroadcasting.kt | 2 -- .../kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt | 1 - .../kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 1 - .../space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 1 - .../kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt | 1 - 17 files changed, 15 insertions(+), 23 deletions(-) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{algebras => }/BroadcastDoubleTensorAlgebra.kt (97%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{algebras => }/DoubleTensorAlgebra.kt (99%) rename kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/{algebras => internal}/TensorLinearStructure.kt (91%) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt index d029348f2..6fbf16a91 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra // Dataset normalization diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index c0ece04ca..78370b517 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra // solving linear system with LUP decomposition diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt index 1998b8d16..874ac8034 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt @@ -7,8 +7,8 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.toDoubleArray import kotlin.math.sqrt diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 497f63b41..42a0a4ba1 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import kotlin.math.abs diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt index d29dbb094..f8ac13d3f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra // simple PCA diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt similarity index 97% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index bc7d90c28..b8530f637 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -3,10 +3,9 @@ * 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.tensors.core.algebras +package space.kscience.kmath.tensors.core import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.internal.array import space.kscience.kmath.tensors.core.internal.broadcastTensors import space.kscience.kmath.tensors.core.internal.broadcastTo diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index e8c0556c2..858532abc 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,8 +1,9 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.Strides import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure +import space.kscience.kmath.tensors.core.internal.TensorLinearStructure /** * Represents [Tensor] over a [MutableBuffer] intended to be used through [DoubleTensor] and [IntTensor] @@ -16,7 +17,7 @@ public open class BufferedTensor internal constructor( /** * Buffer strides based on [TensorLinearStructure] implementation */ - public val linearStructure: TensorLinearStructure + public val linearStructure: Strides get() = TensorLinearStructure(shape) /** diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt similarity index 99% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index cb06432d0..d4a0f1433 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -3,7 +3,7 @@ * 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.tensors.core.algebras +package space.kscience.kmath.tensors.core import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D @@ -11,7 +11,6 @@ import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.internal.dotHelper import space.kscience.kmath.tensors.core.internal.getRandomNormals import space.kscience.kmath.tensors.core.internal.* diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/TensorLinearStructure.kt similarity index 91% rename from kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt rename to kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/TensorLinearStructure.kt index f65e2b955..4bdd987db 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/TensorLinearStructure.kt @@ -3,7 +3,7 @@ * 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.tensors.core.algebras +package space.kscience.kmath.tensors.core.internal import space.kscience.kmath.nd.Strides import kotlin.math.max @@ -44,7 +44,7 @@ internal fun indexFromOffset(offset: Int, strides: IntArray, nDim: Int): IntArra * * @param shape the shape of the tensor. */ -public class TensorLinearStructure(override val shape: IntArray) : Strides { +internal class TensorLinearStructure(override val shape: IntArray) : Strides { override val strides: IntArray get() = stridesFromShape(shape) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt index 0221c961e..f1c158770 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.tensors.core.internal import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra internal fun checkEmptyShape(shape: IntArray) = diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt index 23909f81e..ff78ca64c 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt @@ -11,7 +11,7 @@ import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.* -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import kotlin.math.abs import kotlin.math.min import kotlin.math.sign diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt index 67cb0b842..d965b6bcd 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt @@ -11,7 +11,6 @@ import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.BufferedTensor import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.IntTensor -import space.kscience.kmath.tensors.core.algebras.TensorLinearStructure internal fun BufferedTensor.asTensor(): IntTensor = IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 80c7ab13a..672089a3c 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -1,8 +1,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.internal.* import kotlin.test.Test import kotlin.test.assertTrue diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 4dcc367ca..05fedaa09 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -1,7 +1,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import kotlin.math.* import kotlin.test.Test import kotlin.test.assertTrue diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 77748b15e..fddb37251 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -1,7 +1,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.internal.array import space.kscience.kmath.tensors.core.internal.svd1d import kotlin.math.abs diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index c4f9f94b0..d39b5c365 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -7,7 +7,6 @@ import space.kscience.kmath.nd.as2D import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.toDoubleArray -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.internal.array import space.kscience.kmath.tensors.core.internal.asTensor import space.kscience.kmath.tensors.core.internal.matrixSequence diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index ed858259e..354840719 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -2,7 +2,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.internal.array import kotlin.test.Test import kotlin.test.assertFalse From d31726a0d90de41ced32d211d3d929dd46f5091c Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 13:12:18 +0100 Subject: [PATCH 302/393] produce routine --- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index d4a0f1433..052d8d97e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -56,6 +56,17 @@ public open class DoubleTensorAlgebra : return DoubleTensor(shape, buffer, 0) } + /** + * Constructs a tensor with the specified shape and initializer. + * + * @param shape the desired shape for the tensor. + * @param initializer mapping tensor indices to values. + * @return tensor with the [shape] shape and data generated by initializer. + */ + public fun produce(shape: IntArray, initializer: (IntArray) -> Double): DoubleTensor = + fromArray(shape, + TensorLinearStructure(shape).indices().map(initializer).toMutableList().toDoubleArray()) + override operator fun Tensor.get(i: Int): DoubleTensor { val lastShape = tensor.shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) From e80eefa90f5832de6b3c81487b27e7a355d38358 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 13:12:55 +0100 Subject: [PATCH 303/393] typo corrected --- .../space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 052d8d97e..5baf6c7ad 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -61,7 +61,7 @@ public open class DoubleTensorAlgebra : * * @param shape the desired shape for the tensor. * @param initializer mapping tensor indices to values. - * @return tensor with the [shape] shape and data generated by initializer. + * @return tensor with the [shape] shape and data generated by the [initializer]. */ public fun produce(shape: IntArray, initializer: (IntArray) -> Double): DoubleTensor = fromArray(shape, From d73d03c0558348af0d8de282664206b99fccf681 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 13:36:15 +0100 Subject: [PATCH 304/393] valueOrNull added --- .../kmath/tensors/LinearSystemSolvingWithLUP.kt | 2 +- .../space/kscience/kmath/tensors/OLSWithSVD.kt | 2 +- .../kscience/kmath/tensors/api/TensorAlgebra.kt | 3 ++- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 10 ++++------ .../kmath/tensors/core/internal/checks.kt | 4 ++-- .../kmath/tensors/core/internal/linUtils.kt | 15 ++++++++------- .../tensors/core/TestDoubleLinearOpsAlgebra.kt | 6 +++--- .../kmath/tensors/core/TestDoubleTensor.kt | 2 +- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index 78370b517..4494d6799 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -69,7 +69,7 @@ fun main () { val n = l.shape[0] val x = zeros(intArrayOf(n)) for (i in 0 until n){ - x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)] + x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).valueOrNull()!!) / l[intArrayOf(i, i)] } return x } diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 42a0a4ba1..5d1883e7c 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -60,7 +60,7 @@ fun main() { require(yTrue.shape contentEquals yPred.shape) val diff = yTrue - yPred - return diff.dot(diff).sqrt().value() + return diff.dot(diff).sqrt().valueOrNull()!! } println("MSE: ${mse(alpha, alphaOLS)}") diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index e7f8dc7ae..78a36e229 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -16,11 +16,12 @@ import space.kscience.kmath.operations.Algebra public interface TensorAlgebra: Algebra> { /** + * * Returns a single tensor value of unit dimension. The tensor shape must be equal to [1]. * * @return the value of a scalar tensor. */ - public fun Tensor.value(): T + public fun Tensor.valueOrNull(): T? /** * Each element of the tensor [other] is added to this value. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 5baf6c7ad..bf27a2690 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -35,12 +35,10 @@ public open class DoubleTensorAlgebra : public companion object : DoubleTensorAlgebra() - override fun Tensor.value(): Double { - check(tensor.shape contentEquals intArrayOf(1)) { - "Inconsistent value for tensor of shape ${shape.toList()}" - } - return tensor.mutableBuffer.array()[tensor.bufferStart] - } + override fun Tensor.valueOrNull(): Double? = if(tensor.shape contentEquals intArrayOf(1)) { + // Inconsistent value for tensor of with this shape + tensor.mutableBuffer.array()[tensor.bufferStart] + } else null /** * Constructs a tensor with the specified shape and data. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt index f1c158770..bfbc6334d 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt @@ -58,7 +58,7 @@ internal fun DoubleTensorAlgebra.checkSymmetric( internal fun DoubleTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { checkSymmetric(tensor, epsilon) for (mat in tensor.matrixSequence()) - check(mat.asTensor().detLU().value() > 0.0) { - "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" + check(mat.asTensor().detLU().valueOrNull()!! > 0.0) { + "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().valueOrNull()!!}" } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt index ff78ca64c..5c120c05f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt @@ -12,6 +12,7 @@ import space.kscience.kmath.nd.as2D import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra.Companion.valueOrNull import kotlin.math.abs import kotlin.math.min import kotlin.math.sign @@ -239,14 +240,14 @@ internal fun DoubleTensorAlgebra.qrHelper( val vv = v.as1D() if (j > 0) { for (i in 0 until j) { - r[i, j] = (qT[i] dot matrixT[j]).value() + r[i, j] = (qT[i] dot matrixT[j]).valueOrNull()!! for (k in 0 until n) { val qTi = qT[i].as1D() vv[k] = vv[k] - r[i, j] * qTi[k] } } } - r[j, j] = DoubleTensorAlgebra { (v dot v).sqrt().value() } + r[j, j] = DoubleTensorAlgebra { (v dot v).sqrt().valueOrNull()!! } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } @@ -269,9 +270,9 @@ internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10) while (true) { lastV = v v = b.dot(lastV) - val norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } + val norm = DoubleTensorAlgebra { (v dot v).sqrt().valueOrNull()!! } v = v.times(1.0 / norm) - if (abs(v.dot(lastV).value()) > 1 - epsilon) { + if (abs(v.dot(lastV).valueOrNull()!!) > 1 - epsilon) { return v } } @@ -292,7 +293,7 @@ internal fun DoubleTensorAlgebra.svdHelper( val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) for (i in 0 until u.shape[0]) { for (j in 0 until v.shape[0]) { - outerProduct[i * v.shape[0] + j] = u[i].value() * v[j].value() + outerProduct[i * v.shape[0] + j] = u[i].valueOrNull()!! * v[j].valueOrNull()!! } } a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct)) @@ -303,12 +304,12 @@ internal fun DoubleTensorAlgebra.svdHelper( if (n > m) { v = svd1d(a, epsilon) u = matrix.dot(v) - norm = DoubleTensorAlgebra { (u dot u).sqrt().value() } + norm = DoubleTensorAlgebra { (u dot u).sqrt().valueOrNull()!! } u = u.times(1.0 / norm) } else { u = svd1d(a, epsilon) v = matrix.transpose(0, 1).dot(u) - norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } + norm = DoubleTensorAlgebra { (v dot v).sqrt().valueOrNull()!! } v = v.times(1.0 / norm) } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index fddb37251..99f00edbf 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -46,7 +46,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) ) - assertTrue { abs(m.det().value() - expectedValue) < 1e-5 } + assertTrue { abs(m.det().valueOrNull()!! - expectedValue) < 1e-5 } } @Test @@ -58,7 +58,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) ) - assertTrue { abs(m.det().value() - expectedValue) < 1e-5 } + assertTrue { abs(m.det().valueOrNull()!! - expectedValue) < 1e-5 } } @Test @@ -90,7 +90,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testScalarProduct() = DoubleTensorAlgebra { val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) - assertEquals(a.dot(b).value(), 59.92) + assertEquals(a.dot(b).valueOrNull()!!, 59.92) } @Test diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index d39b5c365..1afdb2263 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -21,7 +21,7 @@ internal class TestDoubleTensor { fun testValue() = DoubleTensorAlgebra { val value = 12.5 val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) - assertEquals(tensor.value(), value) + assertEquals(tensor.valueOrNull()!!, value) } @Test From 5b725a087b81b8c4f9206a4f9098b2cc01c4cd54 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 7 May 2021 15:53:09 +0300 Subject: [PATCH 305/393] new cast --- .../kmath/tensors/core/tensorCasts.kt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt index 814a1bb9b..921bcf97e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt @@ -35,3 +35,35 @@ public fun IntTensor.toIntArray(): IntArray { mutableBuffer[bufferStart + i] } } + +/** + * Casts [Array] to [DoubleTensor] + */ +public fun Array.toDoubleTensor(): DoubleTensor { + val n = size + check(n > 0) { "An empty array cannot be casted to tensor" } + val m = first().size + check(m > 0) { "Inner arrays must have at least 1 argument" } + check(all { size == m }) { "Inner arrays must be the same size" } + + val shape = intArrayOf(n, m) + val buffer = this.flatMap { arr -> arr.map { it } }.toDoubleArray() + + return DoubleTensor(shape, buffer, 0) +} + +/** + * Casts [Array] to [IntTensor] + */ +public fun Array.toIntTensor(): IntTensor { + val n = size + check(n > 0) { "An empty array cannot be casted to tensor" } + val m = first().size + check(m > 0) { "Inner arrays must have at least 1 argument" } + check(all { size == m }) { "Inner arrays must be the same size" } + + val shape = intArrayOf(n, m) + val buffer = this.flatMap { arr -> arr.map { it } }.toIntArray() + + return IntTensor(shape, buffer, 0) +} From 21b5d45b96878e89c464020994b3c7d931464c7f Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 14:13:07 +0100 Subject: [PATCH 306/393] Throwable value method --- .../tensors/LinearSystemSolvingWithLUP.kt | 2 +- .../kscience/kmath/tensors/OLSWithSVD.kt | 2 +- .../kmath/tensors/api/TensorAlgebra.kt | 10 ++++- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 44 ++++++++++++------- .../kmath/tensors/core/internal/checks.kt | 4 +- .../kmath/tensors/core/internal/linUtils.kt | 14 +++--- .../core/TestDoubleLinearOpsAlgebra.kt | 6 +-- .../kmath/tensors/core/TestDoubleTensor.kt | 2 +- 8 files changed, 51 insertions(+), 33 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index 4494d6799..78370b517 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -69,7 +69,7 @@ fun main () { val n = l.shape[0] val x = zeros(intArrayOf(n)) for (i in 0 until n){ - x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).valueOrNull()!!) / l[intArrayOf(i, i)] + x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)] } return x } diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 5d1883e7c..42a0a4ba1 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -60,7 +60,7 @@ fun main() { require(yTrue.shape contentEquals yPred.shape) val diff = yTrue - yPred - return diff.dot(diff).sqrt().valueOrNull()!! + return diff.dot(diff).sqrt().value() } println("MSE: ${mse(alpha, alphaOLS)}") diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 78a36e229..4718b6a58 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -15,13 +15,21 @@ import space.kscience.kmath.operations.Algebra */ public interface TensorAlgebra: Algebra> { + /** + * + * Returns a single tensor value of unit dimension if tensor shape equals to [1]. + * + * @return a nullable value of a potentially scalar tensor. + */ + public fun Tensor.valueOrNull(): T? + /** * * Returns a single tensor value of unit dimension. The tensor shape must be equal to [1]. * * @return the value of a scalar tensor. */ - public fun Tensor.valueOrNull(): T? + public fun Tensor.value(): T /** * Each element of the tensor [other] is added to this value. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index bf27a2690..c1694644f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -35,10 +35,11 @@ public open class DoubleTensorAlgebra : public companion object : DoubleTensorAlgebra() - override fun Tensor.valueOrNull(): Double? = if(tensor.shape contentEquals intArrayOf(1)) { - // Inconsistent value for tensor of with this shape - tensor.mutableBuffer.array()[tensor.bufferStart] - } else null + override fun Tensor.valueOrNull(): Double? = if (tensor.shape contentEquals intArrayOf(1)) + tensor.mutableBuffer.array()[tensor.bufferStart] else null + + override fun Tensor.value(): Double = + valueOrNull() ?: throw IllegalArgumentException("Inconsistent value for tensor of with $shape shape") /** * Constructs a tensor with the specified shape and data. @@ -62,8 +63,10 @@ public open class DoubleTensorAlgebra : * @return tensor with the [shape] shape and data generated by the [initializer]. */ public fun produce(shape: IntArray, initializer: (IntArray) -> Double): DoubleTensor = - fromArray(shape, - TensorLinearStructure(shape).indices().map(initializer).toMutableList().toDoubleArray()) + fromArray( + shape, + TensorLinearStructure(shape).indices().map(initializer).toMutableList().toDoubleArray() + ) override operator fun Tensor.get(i: Int): DoubleTensor { val lastShape = tensor.shape.drop(1).toIntArray() @@ -621,7 +624,7 @@ public open class DoubleTensorAlgebra : keepDim ) - private fun cov(x: DoubleTensor, y:DoubleTensor): Double{ + private fun cov(x: DoubleTensor, y: DoubleTensor): Double { val n = x.shape[0] return ((x - x.mean()) * (y - y.mean())).mean() * n / (n - 1) } @@ -633,10 +636,10 @@ public open class DoubleTensorAlgebra : check(tensors.all { it.shape contentEquals intArrayOf(m) }) { "Tensors must have same shapes" } val resTensor = DoubleTensor( intArrayOf(n, n), - DoubleArray(n * n) {0.0} + DoubleArray(n * n) { 0.0 } ) - for (i in 0 until n){ - for (j in 0 until n){ + for (i in 0 until n) { + for (j in 0 until n) { resTensor[intArrayOf(i, j)] = cov(tensors[i].tensor, tensors[j].tensor) } } @@ -779,8 +782,10 @@ public open class DoubleTensorAlgebra : val qTensor = zeroesLike() val rTensor = zeroesLike() tensor.matrixSequence() - .zip((qTensor.matrixSequence() - .zip(rTensor.matrixSequence()))).forEach { (matrix, qr) -> + .zip( + (qTensor.matrixSequence() + .zip(rTensor.matrixSequence())) + ).forEach { (matrix, qr) -> val (q, r) = qr qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) } @@ -812,9 +817,13 @@ public open class DoubleTensorAlgebra : val vTensor = zeros(commonShape + intArrayOf(min(n, m), m)) tensor.matrixSequence() - .zip(uTensor.matrixSequence() - .zip(sTensor.vectorSequence() - .zip(vTensor.matrixSequence()))).forEach { (matrix, USV) -> + .zip( + uTensor.matrixSequence() + .zip( + sTensor.vectorSequence() + .zip(vTensor.matrixSequence()) + ) + ).forEach { (matrix, USV) -> val matrixSize = matrix.shape.reduce { acc, i -> acc * i } val curMatrix = DoubleTensor( matrix.shape, @@ -918,10 +927,11 @@ public open class DoubleTensorAlgebra : * @return triple of P, L and U tensors */ public fun Tensor.lu(epsilon: Double = 1e-9): Triple { - val (lu, pivots) = this.luFactor(epsilon) + val (lu, pivots) = tensor.luFactor(epsilon) return luPivot(lu, pivots) } override fun Tensor.lu(): Triple = lu(1e-9) - } + + diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt index bfbc6334d..f1c158770 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt @@ -58,7 +58,7 @@ internal fun DoubleTensorAlgebra.checkSymmetric( internal fun DoubleTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { checkSymmetric(tensor, epsilon) for (mat in tensor.matrixSequence()) - check(mat.asTensor().detLU().valueOrNull()!! > 0.0) { - "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().valueOrNull()!!}" + check(mat.asTensor().detLU().value() > 0.0) { + "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt index 5c120c05f..7d3617547 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt @@ -240,14 +240,14 @@ internal fun DoubleTensorAlgebra.qrHelper( val vv = v.as1D() if (j > 0) { for (i in 0 until j) { - r[i, j] = (qT[i] dot matrixT[j]).valueOrNull()!! + r[i, j] = (qT[i] dot matrixT[j]).value() for (k in 0 until n) { val qTi = qT[i].as1D() vv[k] = vv[k] - r[i, j] * qTi[k] } } } - r[j, j] = DoubleTensorAlgebra { (v dot v).sqrt().valueOrNull()!! } + r[j, j] = DoubleTensorAlgebra { (v dot v).sqrt().value() } for (i in 0 until n) { qM[i, j] = vv[i] / r[j, j] } @@ -270,9 +270,9 @@ internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10) while (true) { lastV = v v = b.dot(lastV) - val norm = DoubleTensorAlgebra { (v dot v).sqrt().valueOrNull()!! } + val norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } v = v.times(1.0 / norm) - if (abs(v.dot(lastV).valueOrNull()!!) > 1 - epsilon) { + if (abs(v.dot(lastV).value()) > 1 - epsilon) { return v } } @@ -293,7 +293,7 @@ internal fun DoubleTensorAlgebra.svdHelper( val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) for (i in 0 until u.shape[0]) { for (j in 0 until v.shape[0]) { - outerProduct[i * v.shape[0] + j] = u[i].valueOrNull()!! * v[j].valueOrNull()!! + outerProduct[i * v.shape[0] + j] = u[i].value() * v[j].value() } } a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct)) @@ -304,12 +304,12 @@ internal fun DoubleTensorAlgebra.svdHelper( if (n > m) { v = svd1d(a, epsilon) u = matrix.dot(v) - norm = DoubleTensorAlgebra { (u dot u).sqrt().valueOrNull()!! } + norm = DoubleTensorAlgebra { (u dot u).sqrt().value() } u = u.times(1.0 / norm) } else { u = svd1d(a, epsilon) v = matrix.transpose(0, 1).dot(u) - norm = DoubleTensorAlgebra { (v dot v).sqrt().valueOrNull()!! } + norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } v = v.times(1.0 / norm) } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 99f00edbf..fddb37251 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -46,7 +46,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) ) - assertTrue { abs(m.det().valueOrNull()!! - expectedValue) < 1e-5 } + assertTrue { abs(m.det().value() - expectedValue) < 1e-5 } } @Test @@ -58,7 +58,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { ) ) - assertTrue { abs(m.det().valueOrNull()!! - expectedValue) < 1e-5 } + assertTrue { abs(m.det().value() - expectedValue) < 1e-5 } } @Test @@ -90,7 +90,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testScalarProduct() = DoubleTensorAlgebra { val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8)) val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4)) - assertEquals(a.dot(b).valueOrNull()!!, 59.92) + assertEquals(a.dot(b).value(), 59.92) } @Test diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index 1afdb2263..d39b5c365 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -21,7 +21,7 @@ internal class TestDoubleTensor { fun testValue() = DoubleTensorAlgebra { val value = 12.5 val tensor = fromArray(intArrayOf(1), doubleArrayOf(value)) - assertEquals(tensor.valueOrNull()!!, value) + assertEquals(tensor.value(), value) } @Test From a5b72f201617752033941b50c1789cd5598902ec Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Fri, 7 May 2021 14:15:48 +0100 Subject: [PATCH 307/393] Doc typo --- .../kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 4718b6a58..2eb18ada6 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -16,7 +16,6 @@ import space.kscience.kmath.operations.Algebra public interface TensorAlgebra: Algebra> { /** - * * Returns a single tensor value of unit dimension if tensor shape equals to [1]. * * @return a nullable value of a potentially scalar tensor. @@ -24,7 +23,6 @@ public interface TensorAlgebra: Algebra> { public fun Tensor.valueOrNull(): T? /** - * * Returns a single tensor value of unit dimension. The tensor shape must be equal to [1]. * * @return the value of a scalar tensor. From dde1db7b0afa27162988fcb1b3543afe6187a4d6 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 7 May 2021 23:05:37 +0300 Subject: [PATCH 308/393] fixes --- .../kmath/tensors/core/tensorCasts.kt | 40 ++----------------- 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt index 921bcf97e..4e43ed1e1 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt @@ -9,17 +9,17 @@ import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.internal.tensor /** - * Casts [Tensor] to [DoubleTensor] + * Casts [Tensor] iof [Double] to [DoubleTensor] */ public fun Tensor.toDoubleTensor(): DoubleTensor = this.tensor /** - * Casts [Tensor] to [IntTensor] + * Casts [Tensor] iof [Int] to [IntTensor] */ public fun Tensor.toIntTensor(): IntTensor = this.tensor /** - * @return [DoubleArray] of tensor elements + * Returns [DoubleArray] of tensor elements */ public fun DoubleTensor.toDoubleArray(): DoubleArray { return DoubleArray(numElements) { i -> @@ -28,42 +28,10 @@ public fun DoubleTensor.toDoubleArray(): DoubleArray { } /** - * @return [IntArray] of tensor elements + * Returns [IntArray] of tensor elements */ public fun IntTensor.toIntArray(): IntArray { return IntArray(numElements) { i -> mutableBuffer[bufferStart + i] } } - -/** - * Casts [Array] to [DoubleTensor] - */ -public fun Array.toDoubleTensor(): DoubleTensor { - val n = size - check(n > 0) { "An empty array cannot be casted to tensor" } - val m = first().size - check(m > 0) { "Inner arrays must have at least 1 argument" } - check(all { size == m }) { "Inner arrays must be the same size" } - - val shape = intArrayOf(n, m) - val buffer = this.flatMap { arr -> arr.map { it } }.toDoubleArray() - - return DoubleTensor(shape, buffer, 0) -} - -/** - * Casts [Array] to [IntTensor] - */ -public fun Array.toIntTensor(): IntTensor { - val n = size - check(n > 0) { "An empty array cannot be casted to tensor" } - val m = first().size - check(m > 0) { "Inner arrays must have at least 1 argument" } - check(all { size == m }) { "Inner arrays must be the same size" } - - val shape = intArrayOf(n, m) - val buffer = this.flatMap { arr -> arr.map { it } }.toIntArray() - - return IntTensor(shape, buffer, 0) -} From 11a1624e64d2b779e84d25bf120698b49b400cc1 Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 7 May 2021 23:06:41 +0300 Subject: [PATCH 309/393] fixes --- .../kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt index 4e43ed1e1..142cb2156 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt @@ -9,12 +9,12 @@ import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.internal.tensor /** - * Casts [Tensor] iof [Double] to [DoubleTensor] + * Casts [Tensor] of [Double] to [DoubleTensor] */ public fun Tensor.toDoubleTensor(): DoubleTensor = this.tensor /** - * Casts [Tensor] iof [Int] to [IntTensor] + * Casts [Tensor] of [Int] to [IntTensor] */ public fun Tensor.toIntTensor(): IntTensor = this.tensor From 33e27cd99262d64533ccde72bbdb10b47c75d9fe Mon Sep 17 00:00:00 2001 From: Andrei Kislitsyn Date: Fri, 7 May 2021 23:07:02 +0300 Subject: [PATCH 310/393] fixed --- .../space/kscience/kmath/tensors/core/TestBroadcasting.kt | 2 +- .../kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt | 2 +- .../kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 2 -- .../space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 2 +- .../kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt | 2 +- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 672089a3c..35e605fd9 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -102,4 +102,4 @@ internal class TestBroadcasting { assertTrue(tensor32.mutableBuffer.array() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) } -} \ No newline at end of file +} diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 05fedaa09..3b4c615b4 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -155,4 +155,4 @@ internal class TestDoubleAnalyticTensorAlgebra { )} } -} \ No newline at end of file +} diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index fddb37251..347bb683f 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -194,5 +194,3 @@ private fun DoubleTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double assertTrue(tensor.eq(tensorSVD, epsilon)) } - - diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index d39b5c365..a6c6a7618 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -86,4 +86,4 @@ internal class TestDoubleTensor { assertEquals(ndArray[intArrayOf(0)], 1.0) } -} \ No newline at end of file +} diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 354840719..e7e898008 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -164,4 +164,4 @@ internal class TestDoubleTensorAlgebra { assertFalse(tensor1.eq(tensor3)) } -} \ No newline at end of file +} From e4e661a3bf4946eabd364ac93f62c9a8998e24c3 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 8 May 2021 14:10:57 +0300 Subject: [PATCH 311/393] Update jupyter integration --- .../kscience/kmath/structures/NDField.kt | 2 + kmath-jupyter/build.gradle.kts | 5 +- .../kscience/kmath/jupyter/KMathJupyter.kt | 61 +++++++++++-------- settings.gradle.kts | 16 +++-- 4 files changed, 48 insertions(+), 36 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt index cc1f5f680..501bf98db 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.structures +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import org.nd4j.linalg.factory.Nd4j import space.kscience.kmath.nd.* @@ -22,6 +23,7 @@ internal inline fun measureAndPrint(title: String, block: () -> Unit) { println("$title completed in $time millis") } +@OptIn(DelicateCoroutinesApi::class) fun main() { // initializing Nd4j Nd4j.zeros(0) diff --git a/kmath-jupyter/build.gradle.kts b/kmath-jupyter/build.gradle.kts index 815cb9b8c..83a6a771a 100644 --- a/kmath-jupyter/build.gradle.kts +++ b/kmath-jupyter/build.gradle.kts @@ -7,7 +7,10 @@ dependencies { api(project(":kmath-ast")) api(project(":kmath-complex")) api(project(":kmath-for-real")) - implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.3") +} + +kscience{ + useHtml() } readme { diff --git a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt index e13c92f75..78b25af47 100644 --- a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt +++ b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt @@ -19,49 +19,58 @@ import space.kscience.kmath.operations.RingOperations import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asSequence +/** + * A function for conversion of number to MST for pretty print + */ +public fun Number.toMst(): MST.Numeric = MST.Numeric(this) + @JupyterLibrary internal class KMathJupyter : JupyterIntegration() { private val mathRender = FeaturedMathRendererWithPostProcess.Default private val syntaxRender = MathMLSyntaxRenderer + private fun MST.toDisplayResult(): DisplayResult = HTML(createHTML().div { + unsafe { + +syntaxRender.renderWithStringBuilder(mathRender.render(this@toDisplayResult)) + } + }) + + private fun Unsafe.appendCellValue(it: Any?) { + when (it) { + is Number -> { + val s = StringBuilder() + syntaxRender.renderPart(mathRender.render(MST.Numeric(it)), s) + +s.toString() + } + is MST -> { + val s = StringBuilder() + syntaxRender.renderPart(mathRender.render(it), s) + +s.toString() + } + else -> { + +"" + +it.toString() + +"" + } + } + } + override fun Builder.onLoaded() { import( "space.kscience.kmath.ast.*", "space.kscience.kmath.ast.rendering.*", + "space.kscience.kmath.structures.*", "space.kscience.kmath.operations.*", "space.kscience.kmath.expressions.*", + "space.kscience.kmath.nd.*", "space.kscience.kmath.misc.*", "space.kscience.kmath.real.*", ) - fun MST.toDisplayResult(): DisplayResult = HTML(createHTML().div { - unsafe { - +syntaxRender.renderWithStringBuilder(mathRender.render(this@toDisplayResult)) - } - }) + import("space.kscience.kmath.jupyter.toMst") render { it.toDisplayResult() } - render { MST.Numeric(it).toDisplayResult() } - - fun Unsafe.appendCellValue(it: Any?) { - when (it) { - is Number -> { - val s = StringBuilder() - syntaxRender.renderPart(mathRender.render(MST.Numeric(it)), s) - +s.toString() - } - is MST -> { - val s = StringBuilder() - syntaxRender.renderPart(mathRender.render(it), s) - +s.toString() - } - else -> { - +"" - +it.toString() - +"" - } - } - } + //render { MST.Numeric(it).toDisplayResult() } render> { structure -> HTML(createHTML().div { diff --git a/settings.gradle.kts b/settings.gradle.kts index 90cc4aef1..27e74c902 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,25 +1,23 @@ pluginManagement { repositories { - mavenLocal() mavenCentral() gradlePluginPortal() maven("https://repo.kotlin.link") } - val toolsVersion = "0.9.5-dev-2" - val kotlinVersion = "1.5.0-RC" + val toolsVersion = "0.9.6" + val kotlinVersion = "1.5.0" plugins { + id("ru.mipt.npm.gradle.project") version toolsVersion + id("ru.mipt.npm.gradle.mpp") version toolsVersion + id("ru.mipt.npm.gradle.jvm") version toolsVersion kotlin("multiplatform") version kotlinVersion kotlin("jvm") version kotlinVersion kotlin("plugin.allopen") version kotlinVersion id("org.jetbrains.kotlinx.benchmark") version "0.3.0" - id("ru.mipt.npm.gradle.project") version toolsVersion - id("ru.mipt.npm.gradle.mpp") version toolsVersion - id("ru.mipt.npm.gradle.jvm") version toolsVersion - kotlin("jupyter.api") version "0.9.0.12" - kotlin("jvm") version kotlinVersion - kotlin("plugin.allopen") version kotlinVersion + kotlin("jupyter.api") version "0.9.1-61" + } } From 7ce0829597af279f54d368c4ef4ce643e7fa6f5a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 8 May 2021 14:20:16 +0300 Subject: [PATCH 312/393] 0.3.0-dev-8. Cleanup --- CHANGELOG.md | 1 + build.gradle.kts | 2 +- .../space/kscience/kmath/tensors/NeuralNetwork.kt | 8 ++++---- .../kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt | 2 +- .../kotlin/space/kscience/kmath/complex/Complex.kt | 9 +++++---- .../kotlin/space/kscience/kmath/complex/Quaternion.kt | 10 +++++----- .../kscience/kmath/stat/CommonsDistributionsTest.kt | 5 ++--- 7 files changed, 19 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5542b6563..286511327 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ - `contentEquals` from Buffer. It moved to the companion. - MSTExpression - Expression algebra builders +- Comples and Quaternion no longer are elements. ### Fixed - Ring inherits RingOperations, not GroupOperations diff --git a/build.gradle.kts b/build.gradle.kts index 760bf1aee..406a46810 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.0-dev-7" + version = "0.3.0-dev-8" } subprojects { diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt index 874ac8034..5b3c2e1cd 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt @@ -6,8 +6,8 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.toDoubleArray import kotlin.math.sqrt @@ -106,6 +106,7 @@ fun accuracy(yPred: DoubleTensor, yTrue: DoubleTensor): Double { } // neural network class +@OptIn(ExperimentalStdlibApi::class) class NeuralNetwork(private val layers: List) { private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra { @@ -120,7 +121,7 @@ class NeuralNetwork(private val layers: List) { (-onesForAnswers + softmaxValue) / (yPred.shape[0].toDouble()) } - @OptIn(ExperimentalStdlibApi::class) + private fun forward(x: DoubleTensor): List { var input = x @@ -133,7 +134,6 @@ class NeuralNetwork(private val layers: List) { } } - @OptIn(ExperimentalStdlibApi::class) private fun train(xTrain: DoubleTensor, yTrain: DoubleTensor) { val layerInputs = buildList { add(xTrain) @@ -180,7 +180,7 @@ fun main() { val features = 5 val sampleSize = 250 val trainSize = 180 - val testSize = sampleSize - trainSize + //val testSize = sampleSize - trainSize // take sample of features from normal distribution val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5 diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index 42a0a4ba1..b42602988 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -48,7 +48,7 @@ fun main() { // inverse Sigma matrix can be restored from singular values with diagonalEmbedding function - val sigma = diagonalEmbedding(singValues.map{ x -> if (abs(x) < 1e-3) 0.0 else 1.0/x }) + val sigma = diagonalEmbedding(singValues.map{ if (abs(it) < 1e-3) 0.0 else 1.0/it }) val alphaOLS = v dot sigma dot u.transpose() dot y println("Estimated alpha:\n" + diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt index 8d626c17d..8e28337f6 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt @@ -9,7 +9,10 @@ import space.kscience.kmath.memory.MemoryReader import space.kscience.kmath.memory.MemorySpec import space.kscience.kmath.memory.MemoryWriter import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.operations.Norm +import space.kscience.kmath.operations.NumbersAddOperations +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MemoryBuffer import space.kscience.kmath.structures.MutableBuffer @@ -180,12 +183,10 @@ public object ComplexField : ExtendedField, Norm, Num * @property im The imaginary part. */ @OptIn(UnstableKMathAPI::class) -public data class Complex(val re: Double, val im: Double) : FieldElement { +public data class Complex(val re: Double, val im: Double) { public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble()) public constructor(re: Number) : this(re.toDouble(), 0.0) - public override val context: ComplexField get() = ComplexField - public override fun toString(): String = "($re + i*$im)" public companion object : MemorySpec { diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index 382b5cc05..c59aabdcb 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -27,8 +27,10 @@ public val Quaternion.conjugate: Quaternion */ public val Quaternion.reciprocal: Quaternion get() { - val n = QuaternionField { norm(this@reciprocal) } - return conjugate / (n * n) + QuaternionField { + val n = norm(this@reciprocal) + return conjugate / (n * n) + } } /** @@ -198,7 +200,7 @@ public object QuaternionField : Field, Norm, @OptIn(UnstableKMathAPI::class) public data class Quaternion( val w: Double, val x: Double, val y: Double, val z: Double, -) : FieldElement { +) { public constructor(w: Number, x: Number, y: Number, z: Number) : this( w.toDouble(), x.toDouble(), @@ -219,8 +221,6 @@ public data class Quaternion( require(!z.isNaN()) { "x-component of quaternion is not-a-number" } } - public override val context: QuaternionField get() = QuaternionField - /** * Returns a string representation of this quaternion. */ diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt index 066fd69e6..19c01e099 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -5,15 +5,14 @@ package space.kscience.kmath.stat -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import space.kscience.kmath.samplers.GaussianSampler internal class CommonsDistributionsTest { @Test - fun testNormalDistributionSuspend() = GlobalScope.launch { + fun testNormalDistributionSuspend() = runBlocking { val distribution = GaussianSampler(7.0, 2.0) val generator = RandomGenerator.default(1) val sample = distribution.sample(generator).nextBuffer(1000) From 6d78bb8d91a0236bb4f962c66a40ea74becdbcea Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 8 May 2021 14:36:37 +0300 Subject: [PATCH 313/393] 0.3.0-dev-8. Readme update --- README.md | 4 +- kmath-ast/README.md | 24 +- kmath-complex/README.md | 6 +- kmath-core/README.md | 6 +- kmath-ejml/README.md | 6 +- kmath-for-real/README.md | 6 +- kmath-functions/README.md | 6 +- kmath-nd4j/README.md | 6 +- kmath-tensors/README.md | 25 +- license/COPYRIGHT.txt | 15 - license/COPYRIGHT_HEADER.txt | 4 - license/LICENSE.txt | 201 ----------- license/README.md | 63 ---- license/third_party/cm_license.txt | 457 -------------------------- license/third_party/crng_license.txt | 275 ---------------- license/third_party/numky_license.txt | 201 ----------- 16 files changed, 47 insertions(+), 1258 deletions(-) delete mode 100644 license/COPYRIGHT.txt delete mode 100644 license/COPYRIGHT_HEADER.txt delete mode 100644 license/LICENSE.txt delete mode 100644 license/README.md delete mode 100644 license/third_party/cm_license.txt delete mode 100644 license/third_party/crng_license.txt delete mode 100644 license/third_party/numky_license.txt diff --git a/README.md b/README.md index 8796d7aac..c8da21b64 100644 --- a/README.md +++ b/README.md @@ -288,8 +288,8 @@ repositories { } dependencies { - api("space.kscience:kmath-core:0.3.0-dev-7") - // api("space.kscience:kmath-core-jvm:0.3.0-dev-7") for jvm-specific version + api("space.kscience:kmath-core:0.3.0-dev-8") + // api("space.kscience:kmath-core-jvm:0.3.0-dev-8") for jvm-specific version } ``` diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 26ee98ba5..646ab4306 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -10,7 +10,7 @@ Performance and visualization extensions to MST API. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-8`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0-dev-7' + implementation 'space.kscience:kmath-ast:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0-dev-7") + implementation("space.kscience:kmath-ast:0.3.0-dev-8") } ``` @@ -144,7 +144,7 @@ import space.kscience.kmath.misc.* @OptIn(UnstableKMathAPI::class) public fun main() { - val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath() + val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(12)+x^(2/3)".parseMath() val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst) val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax) println("LaTeX:") @@ -158,9 +158,9 @@ public fun main() { Result LaTeX: -![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{-12}) +![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3}) -Result MathML (embedding MathML is not allowed by GitHub Markdown): +Result MathML (can be used with MathJax or other renderers):
diff --git a/kmath-kotlingrad/README.md b/kmath-kotlingrad/README.md index 31c7bb819..304a0639b 100644 --- a/kmath-kotlingrad/README.md +++ b/kmath-kotlingrad/README.md @@ -8,7 +8,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0-dev-13`. +The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0-dev-14`. **Gradle:** ```gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-kotlingrad:0.3.0-dev-13' + implementation 'space.kscience:kmath-kotlingrad:0.3.0-dev-14' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-kotlingrad:0.3.0-dev-13") + implementation("space.kscience:kmath-kotlingrad:0.3.0-dev-14") } ``` diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 1c945f06a..5cbb31d5a 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-13`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-14`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0-dev-13' + implementation 'space.kscience:kmath-nd4j:0.3.0-dev-14' } ``` **Gradle Kotlin DSL:** @@ -30,7 +30,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0-dev-13") + implementation("space.kscience:kmath-nd4j:0.3.0-dev-14") } ``` diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index abcc02962..6e890a937 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -7,9 +7,8 @@ description = "ND4J NDStructure implementation and according NDAlgebra classes" dependencies { api(project(":kmath-tensors")) - api("org.nd4j:nd4j-api:1.0.0-beta7") - testImplementation("org.nd4j:nd4j-native:1.0.0-beta7") - testImplementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") + api("org.nd4j:nd4j-api:1.0.0-M1") + testImplementation("org.nd4j:nd4j-native-platform:1.0.0-M1") testImplementation("org.slf4j:slf4j-simple:1.7.30") } diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index dd21a9f2f..6b991d5df 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -9,7 +9,7 @@ Common linear algebra operations on tensors. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-13`. +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-14`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensors:0.3.0-dev-13' + implementation 'space.kscience:kmath-tensors:0.3.0-dev-14' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensors:0.3.0-dev-13") + implementation("space.kscience:kmath-tensors:0.3.0-dev-14") } ``` diff --git a/settings.gradle.kts b/settings.gradle.kts index 063c69280..02b75cddc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,7 +6,7 @@ pluginManagement { } val toolsVersion = "0.10.0" - val kotlinVersion = "1.5.0" + val kotlinVersion = "1.5.20" plugins { id("ru.mipt.npm.gradle.project") version toolsVersion @@ -17,7 +17,6 @@ pluginManagement { kotlin("plugin.allopen") version kotlinVersion id("org.jetbrains.kotlinx.benchmark") version "0.3.1" kotlin("jupyter.api") version "0.10.0-25" - } } @@ -45,5 +44,5 @@ include( ":kmath-symja", ":kmath-jafama", ":examples", - ":benchmarks" + ":benchmarks", )
@@ -211,10 +211,20 @@ Result MathML (embedding MathML is not allowed by GitHub Markdown): - - 12 + + + + + x + + + 2 + / + 3 + + ``` diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 06e10fa7a..ee5ad416f 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-8`. **Gradle:** ```gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0-dev-7' + implementation 'space.kscience:kmath-complex:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0-dev-7") + implementation("space.kscience:kmath-complex:0.3.0-dev-8") } ``` diff --git a/kmath-core/README.md b/kmath-core/README.md index 36b30efcc..7283a18ce 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-8`. **Gradle:** ```gradle @@ -25,7 +25,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0-dev-7' + implementation 'space.kscience:kmath-core:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -36,6 +36,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0-dev-7") + implementation("space.kscience:kmath-core:0.3.0-dev-8") } ``` diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index 97c5ae115..cb12ef98d 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-8`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0-dev-7' + implementation 'space.kscience:kmath-ejml:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0-dev-7") + implementation("space.kscience:kmath-ejml:0.3.0-dev-8") } ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index a77f9d98b..8b3b8e9e0 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-8`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0-dev-7' + implementation 'space.kscience:kmath-for-real:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0-dev-7") + implementation("space.kscience:kmath-for-real:0.3.0-dev-8") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 2090ede3e..4f592c845 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-8`. **Gradle:** ```gradle @@ -21,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0-dev-7' + implementation 'space.kscience:kmath-functions:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0-dev-7") + implementation("space.kscience:kmath-functions:0.3.0-dev-8") } ``` diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index b4b586ea9..5f33c1db1 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-8`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0-dev-7' + implementation 'space.kscience:kmath-nd4j:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** @@ -30,7 +30,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0-dev-7") + implementation("space.kscience:kmath-nd4j:0.3.0-dev-8") } ``` diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index a81b7277c..7ece44217 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -1,40 +1,35 @@ # Module kmath-tensors -Common operations on tensors, the API consists of: +Common linear algebra operations on tensors. + + - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) + - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. + - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. - - [TensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic algebra operations on tensors (plus, dot, etc.) - - [TensorPartialDivisionAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt) : Emulates an algebra over a field - - [LinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Linear algebra operations including LU, QR, Cholesky LL and SVD decompositions - - [AnalyticTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt) : Element-wise analytic operations -The library offers a multiplatform implementation for this interface over the `Double`'s. As a highlight, the user can find: - - [BroadcastDoubleTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic algebra operations implemented with broadcasting. - - [DoubleLinearOpsTensorAlgebra](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/DoubleLinearOpsTensorAlgebra.kt) : Contains the power method for SVD and the spectrum of symmetric matrices. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-7`. +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-8`. **Gradle:** ```gradle repositories { maven { url 'https://repo.kotlin.link' } - maven { url 'https://dl.bintray.com/hotkeytlt/maven' } - maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap + mavenCentral() } dependencies { - implementation 'space.kscience:kmath-tensors:0.3.0-dev-7' + implementation 'space.kscience:kmath-tensors:0.3.0-dev-8' } ``` **Gradle Kotlin DSL:** ```kotlin repositories { maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap - maven("https://dl.bintray.com/hotkeytlt/maven") // required for a + mavenCentral() } dependencies { - implementation("space.kscience:kmath-tensors:0.3.0-dev-7") + implementation("space.kscience:kmath-tensors:0.3.0-dev-8") } ``` diff --git a/license/COPYRIGHT.txt b/license/COPYRIGHT.txt deleted file mode 100644 index 7bf2faffd..000000000 --- a/license/COPYRIGHT.txt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ \ No newline at end of file diff --git a/license/COPYRIGHT_HEADER.txt b/license/COPYRIGHT_HEADER.txt deleted file mode 100644 index 3e7d28489..000000000 --- a/license/COPYRIGHT_HEADER.txt +++ /dev/null @@ -1,4 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ \ No newline at end of file diff --git a/license/LICENSE.txt b/license/LICENSE.txt deleted file mode 100644 index 84b106a07..000000000 --- a/license/LICENSE.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2018-2021 KMath contributors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/license/README.md b/license/README.md deleted file mode 100644 index cfef3de79..000000000 --- a/license/README.md +++ /dev/null @@ -1,63 +0,0 @@ -The Apache 2 license (given in full in LICENSE.txt) applies to all code in this repository, which is copyright by the -contributors of KMath. The following sections of the repository contain third-party code, to which different licenses -may apply: - -## KMath Libraries - -The following modules contain third-party code and are incorporated into the KMath Libraries: - -- Path: kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt - - License: Apache 2 ([cm](third_party/cm_license.txt)) - - Origin: Derived from Apache Commons Math, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt - - License: Apache 2 ([cm](third_party/cm_license.txt)) - - Origin: Derived from Apache Commons Math, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LoessInterpolator.kt - - License: Apache 2 ([cm](third_party/cm_license.txt)) - - Origin: Derived from Apache Commons Math, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt - - License: Apache 2 ([cm](third_party/cm_license.txt)) - - Origin: Derived from Apache Commons Math, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt - - License: Apache 2 ([numky](third_party/numky_license.txt)) - - Origin: Initial implementation was taken from Numky -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation -- Path: - - License: Apache 2 ([cm](third_party/crng_license.txt)) - - Origin: Derived from Apache Commons RNG, (c) 2001-2020 The Apache Software Foundation - \ No newline at end of file diff --git a/license/third_party/cm_license.txt b/license/third_party/cm_license.txt deleted file mode 100644 index 6172c3fb2..000000000 --- a/license/third_party/cm_license.txt +++ /dev/null @@ -1,457 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - -Apache Commons Math includes the following code provided to the ASF under the -Apache License 2.0: - - - The inverse error function implementation in the Erf class is based on CUDA - code developed by Mike Giles, Oxford-Man Institute of Quantitative Finance, - and published in GPU Computing Gems, volume 2, 2010 (grant received on - March 23th 2013) - - The LinearConstraint, LinearObjectiveFunction, LinearOptimizer, - RelationShip, SimplexSolver and SimplexTableau classes in package - org.apache.commons.math3.optimization.linear include software developed by - Benjamin McCann (http://www.benmccann.com) and distributed with - the following copyright: Copyright 2009 Google Inc. (grant received on - March 16th 2009) - - The class "org.apache.commons.math3.exception.util.LocalizedFormatsTest" which - is an adapted version of "OrekitMessagesTest" test class for the Orekit library - - The "org.apache.commons.math3.analysis.interpolation.HermiteInterpolator" - has been imported from the Orekit space flight dynamics library. - -=============================================================================== - - - -APACHE COMMONS MATH DERIVATIVE WORKS: - -The Apache commons-math library includes a number of subcomponents -whose implementation is derived from original sources written -in C or Fortran. License terms of the original sources -are reproduced below. - -=============================================================================== -For the lmder, lmpar and qrsolv Fortran routine from minpack and translated in -the LevenbergMarquardtOptimizer class in package -org.apache.commons.math3.optimization.general -Original source copyright and license statement: - -Minpack Copyright Notice (1999) University of Chicago. All rights reserved - -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the -following conditions are met: - -1. Redistributions of source code must retain the above -copyright notice, this list of conditions and the following -disclaimer. - -2. Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following -disclaimer in the documentation and/or other materials -provided with the distribution. - -3. The end-user documentation included with the -redistribution, if any, must include the following -acknowledgment: - - "This product includes software developed by the - University of Chicago, as Operator of Argonne National - Laboratory. - -Alternately, this acknowledgment may appear in the software -itself, if and wherever such third-party acknowledgments -normally appear. - -4. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" -WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE -UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND -THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE -OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY -OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR -USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF -THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4) -DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION -UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL -BE CORRECTED. - -5. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT -HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF -ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT, -INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF -ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF -PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER -SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT -(INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE, -EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE -POSSIBILITY OF SUCH LOSS OR DAMAGES. -=============================================================================== - -Copyright and license statement for the odex Fortran routine developed by -E. Hairer and G. Wanner and translated in GraggBulirschStoerIntegrator class -in package org.apache.commons.math3.ode.nonstiff: - - -Copyright (c) 2004, Ernst Hairer - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -- Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -=============================================================================== - -Copyright and license statement for the original Mersenne twister C -routines translated in MersenneTwister class in package -org.apache.commons.math3.random: - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -=============================================================================== - -The initial code for shuffling an array (originally in class -"org.apache.commons.math3.random.RandomDataGenerator", now replaced by -a method in class "org.apache.commons.math3.util.MathArrays") was -inspired from the algorithm description provided in -"Algorithms", by Ian Craw and John Pulham (University of Aberdeen 1999). -The textbook (containing a proof that the shuffle is uniformly random) is -available here: - http://citeseerx.ist.psu.edu/viewdoc/download;?doi=10.1.1.173.1898&rep=rep1&type=pdf - -=============================================================================== -License statement for the direction numbers in the resource files for Sobol sequences. - ------------------------------------------------------------------------------ -Licence pertaining to sobol.cc and the accompanying sets of direction numbers - ------------------------------------------------------------------------------ -Copyright (c) 2008, Frances Y. Kuo and Stephen Joe -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the names of the copyright holders nor the names of the - University of New South Wales and the University of Waikato - and its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -=============================================================================== - -The initial commit of package "org.apache.commons.math3.ml.neuralnet" is -an adapted version of code developed in the context of the Data Processing -and Analysis Consortium (DPAC) of the "Gaia" project of the European Space -Agency (ESA). -=============================================================================== - -The initial commit of the class "org.apache.commons.math3.special.BesselJ" is -an adapted version of code translated from the netlib Fortran program, rjbesl -http://www.netlib.org/specfun/rjbesl by R.J. Cody at Argonne National -Laboratory (USA). There is no license or copyright statement included with the -original Fortran sources. -=============================================================================== - - -The BracketFinder (package org.apache.commons.math3.optimization.univariate) -and PowellOptimizer (package org.apache.commons.math3.optimization.general) -classes are based on the Python code in module "optimize.py" (version 0.5) -developed by Travis E. Oliphant for the SciPy library (http://www.scipy.org/) -Copyright © 2003-2009 SciPy Developers. - -SciPy license -Copyright © 2001, 2002 Enthought, Inc. -All rights reserved. - -Copyright © 2003-2013 SciPy Developers. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of Enthought nor the names of the SciPy Developers may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -=============================================================================== diff --git a/license/third_party/crng_license.txt b/license/third_party/crng_license.txt deleted file mode 100644 index dec0e2a5c..000000000 --- a/license/third_party/crng_license.txt +++ /dev/null @@ -1,275 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -================================================================================ - -Class "org.apache.commons.rng.core.source64.MersenneTwister64" contains -Java code partly ported from the reference implementation in C. -That source file contained the following notice: - - Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -================================================================================ - -Class "org.apache.commons.rng.core.source32.MersenneTwister" contains -Java code partly ported from the reference implementation in C. -That source file contained the following notice: - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -================================================================================ \ No newline at end of file diff --git a/license/third_party/numky_license.txt b/license/third_party/numky_license.txt deleted file mode 100644 index f49a4e16e..000000000 --- a/license/third_party/numky_license.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file From ca02f5406d06d18d07909f3d48508e1a99701fa5 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 8 May 2021 18:07:53 +0300 Subject: [PATCH 314/393] Update gradle.properties Increase metaspace for dokka --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7e9516660..3aaade368 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,5 +9,5 @@ kotlin.mpp.stability.nowarn=true kotlin.native.enableDependencyPropagation=false kotlin.parallel.tasks.in.project=true org.gradle.configureondemand=true -org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G +org.gradle.jvmargs=-XX:MaxMetaspaceSize=2G org.gradle.parallel=true From bbef697b7dc553281af826ece76373af469fab0e Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 9 May 2021 18:10:06 +0700 Subject: [PATCH 315/393] Document and change retention for UnstableKMathAPI --- .../kotlin/space/kscience/kmath/misc/annotations.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt index 206e4e000..7f53d96ce 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt @@ -5,5 +5,13 @@ package space.kscience.kmath.misc +/** + * Marks declarations that are still experimental in the KMath APIs, which means that the design of the corresponding + * declarations has open issues which may (or may not) lead to their changes in the future. Roughly speaking, there is + * a chance that those declarations will be deprecated in the near future or the semantics of their behavior may change + * in some way that may break some code. + */ +@MustBeDocumented +@Retention(value = AnnotationRetention.BINARY) @RequiresOptIn("This API is unstable and could change in future", RequiresOptIn.Level.WARNING) public annotation class UnstableKMathAPI From e2920ed68390bf29ee0854da85d69efd53c6a5a3 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 9 May 2021 16:40:10 +0700 Subject: [PATCH 316/393] Promote kmath-kotlingrad to experimental alongside minor documentation and API changes --- CHANGELOG.md | 3 +- README.md | 9 +++-- kmath-kotlingrad/README.md | 34 +++++++++++++++++++ kmath-kotlingrad/build.gradle.kts | 20 +++++++++-- kmath-kotlingrad/docs/README-TEMPLATE.md | 7 ++++ .../kotlingrad/DifferentiableMstExpression.kt | 17 +++++----- .../kscience/kmath/kotlingrad/KMathNumber.kt | 25 +++++++++----- .../kmath/kotlingrad/ScalarsAdapters.kt | 26 +++++++------- .../kmath/kotlingrad/AdaptingTests.kt | 6 +--- 9 files changed, 106 insertions(+), 41 deletions(-) create mode 100644 kmath-kotlingrad/README.md create mode 100644 kmath-kotlingrad/docs/README-TEMPLATE.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 286511327..4fba361d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - Move MST to core - Separated benchmarks and examples - Rewritten EJML module without ejml-simple +- Stability of kmath-ast and kmath-kotilngrad promoted to EXPERIMENTAL. ### Deprecated @@ -35,7 +36,7 @@ - `contentEquals` from Buffer. It moved to the companion. - MSTExpression - Expression algebra builders -- Comples and Quaternion no longer are elements. +- Complex and Quaternion no longer are elements. ### Fixed - Ring inherits RingOperations, not GroupOperations diff --git a/README.md b/README.md index c8da21b64..3b4387c1b 100644 --- a/README.md +++ b/README.md @@ -207,9 +207,14 @@ One can still use generic algebras though.
* ### [kmath-kotlingrad](kmath-kotlingrad) -> +> Functions, integration and interpolation > -> **Maturity**: PROTOTYPE +> **Maturity**: EXPERIMENTAL +> +> **Features:** +> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : MST based DifferentiableExpression. +> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : Conversions between Kotlin∇'s SFun and MST +
* ### [kmath-memory](kmath-memory) diff --git a/kmath-kotlingrad/README.md b/kmath-kotlingrad/README.md new file mode 100644 index 000000000..686df3271 --- /dev/null +++ b/kmath-kotlingrad/README.md @@ -0,0 +1,34 @@ +# Module kmath-kotlingrad + +[Kotlin∇](https://github.com/breandan/kotlingrad) integration module. + + - [differentiable-mst-expression](src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : MST based DifferentiableExpression. + - [differentiable-mst-expression](src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : Conversions between Kotlin∇'s SFun and MST + + +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0-dev-8`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + mavenCentral() +} + +dependencies { + implementation 'space.kscience:kmath-kotlingrad:0.3.0-dev-8' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + mavenCentral() +} + +dependencies { + implementation("space.kscience:kmath-kotlingrad:0.3.0-dev-8") +} +``` diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index ed5b5bcb4..0e8e49971 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -4,11 +4,27 @@ plugins { } dependencies { - api("com.github.breandan:kaliningraph:0.1.4") + api("com.github.breandan:kaliningraph:0.1.6") api("com.github.breandan:kotlingrad:0.4.5") api(project(":kmath-ast")) } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + description = "Functions, integration and interpolation" + maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + + feature( + "differentiable-mst-expression", + "src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt", + ) { + "MST based DifferentiableExpression." + } + + feature( + "differentiable-mst-expression", + "src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt", + ) { + "Conversions between Kotlin∇'s SFun and MST" + } } diff --git a/kmath-kotlingrad/docs/README-TEMPLATE.md b/kmath-kotlingrad/docs/README-TEMPLATE.md new file mode 100644 index 000000000..ac38c849b --- /dev/null +++ b/kmath-kotlingrad/docs/README-TEMPLATE.md @@ -0,0 +1,7 @@ +# Module kmath-kotlingrad + +[Kotlin∇](https://www.htmlsymbols.xyz/unicode/U+2207) integration module. + +${features} + +${artifact} diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt index 222145d2d..8c6745c79 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.api.SFun +import edu.umontreal.kotlingrad.api.SVar import space.kscience.kmath.expressions.DifferentiableExpression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MstAlgebra @@ -14,20 +15,20 @@ import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.NumericAlgebra /** - * Represents wrapper of [MstExpression] implementing [DifferentiableExpression]. + * Represents [MST] based [DifferentiableExpression]. * - * The principle of this API is converting the [mst] to an [SFun], differentiating it with Kotlin∇, then converting - * [SFun] back to [MST]. + * The principle of this API is converting the [mst] to an [SFun], differentiating it with + * [Kotlin∇](https://github.com/breandan/kotlingrad), then converting [SFun] back to [MST]. * - * @param T the type of number. - * @param A the [NumericAlgebra] of [T]. - * @property expr the underlying [MstExpression]. + * @param T The type of number. + * @param A The [NumericAlgebra] of [T]. + * @property algebra The [A] instance. + * @property mst The [MST] node. */ public class DifferentiableMstExpression>( public val algebra: A, public val mst: MST, ) : DifferentiableExpression> { - public override fun invoke(arguments: Map): T = mst.interpret(algebra, arguments) public override fun derivativeOrNull(symbols: List): DifferentiableMstExpression = @@ -35,7 +36,7 @@ public class DifferentiableMstExpression>( algebra, symbols.map(Symbol::identity) .map(MstAlgebra::bindSymbol) - .map { it.toSVar>() } + .map>>(MST.Symbolic::toSVar) .fold(mst.toSFun(), SFun>::d) .toMst(), ) diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt index 0c3768dcc..9c9d07b81 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt @@ -5,19 +5,26 @@ package space.kscience.kmath.kotlingrad -import edu.umontreal.kotlingrad.api.RealNumber import edu.umontreal.kotlingrad.api.SConst import space.kscience.kmath.operations.NumericAlgebra /** - * Implements [RealNumber] by delegating its functionality to [NumericAlgebra]. + * Implements [SConst] by delegating its functionality to [NumericAlgebra]. * - * @param T the type of number. - * @param A the [NumericAlgebra] of [T]. - * @property algebra the algebra. - * @param value the value of this number. + * @param T The type of number. + * @param A The [NumericAlgebra] over [T]. + * @property algebra The algebra. + * @property value The value of this number. */ -public class KMathNumber(public val algebra: A, value: T) : - RealNumber, T>(value) where T : Number, A : NumericAlgebra { - public override fun wrap(number: Number): SConst> = SConst(algebra.number(number)) +public class KMathNumber(public val algebra: A, public override val value: T) : + SConst>(value) where T : Number, A : NumericAlgebra { + /** + * Returns a string representation of the [value]. + */ + public override fun toString(): String = value.toString() + + /** + * Wraps [Number] to [KMathNumber]. + */ + public override fun wrap(number: Number): KMathNumber = KMathNumber(algebra, algebra.number(number)) } diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt index f65d2948d..bee2c9e3e 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -15,16 +15,16 @@ import space.kscience.kmath.operations.* /** * Maps [SVar] to [MST.Symbolic] directly. * - * @receiver the variable. - * @return a node. + * @receiver The variable. + * @returnAa node. */ public fun > SVar.toMst(): MST.Symbolic = MstAlgebra.bindSymbol(name) /** * Maps [SVar] to [MST.Numeric] directly. * - * @receiver the constant. - * @return a node. + * @receiver The constant. + * @return A node. */ public fun > SConst.toMst(): MST.Numeric = MstAlgebra.number(doubleValue) @@ -49,8 +49,8 @@ public fun > SConst.toMst(): MST.Numeric = MstAlgebra.number(doub * - [VSumAll] is requested to be evaluated; * - [Derivative] is requested to be evaluated. * - * @receiver the scalar function. - * @return a node. + * @receiver The scalar function. + * @return A node. */ public fun > SFun.toMst(): MST = MstExtendedField { when (this@toMst) { @@ -74,17 +74,16 @@ public fun > SFun.toMst(): MST = MstExtendedField { /** * Maps [MST.Numeric] to [SConst] directly. * - * @receiver the node. - * @return a new constant. + * @receiver The node. + * @return A new constant. */ public fun > MST.Numeric.toSConst(): SConst = SConst(value) /** * Maps [MST.Symbolic] to [SVar] directly. * - * @receiver the node. - * @param proto the prototype instance. - * @return a new variable. + * @receiver The node. + * @return A new variable. */ internal fun > MST.Symbolic.toSVar(): SVar = SVar(value) @@ -98,9 +97,8 @@ internal fun > MST.Symbolic.toSVar(): SVar = SVar(value) * - [MST.Unary] -> [Negative], [Sine], [Cosine], [Tangent], [Power], [Log]; * - [MST.Binary] -> [Sum], [Prod], [Power]. * - * @receiver the node. - * @param proto the prototype instance. - * @return a scalar function. + * @receiver The node. + * @return A scalar function. */ public fun > MST.toSFun(): SFun = when (this) { is MST.Numeric -> toSConst() diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index 3ed73451d..85c964c58 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -10,7 +10,7 @@ import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.MstAlgebra import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol +import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals @@ -65,8 +65,4 @@ internal class AdaptingTests { assertEquals(actualDerivative(x to 0.1), expectedDerivative(x to 0.1)) } - - private companion object { - private val x by symbol - } } From 1716b7f5d1d871610961419fd425c49730ea1a2f Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Mon, 10 May 2021 17:57:49 +0300 Subject: [PATCH 317/393] Fast power is added --- .../kscience/kmath/benchmarks/BigIntBenchmark.kt | 6 ++---- .../space/kscience/kmath/operations/Algebra.kt | 15 +++++++++++++++ .../kmath/operations/BigIntAlgebraTest.kt | 14 ++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index b9a10c774..33c659fca 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -15,15 +15,13 @@ import space.kscience.kmath.operations.BigIntField import space.kscience.kmath.operations.JBigIntegerField import space.kscience.kmath.operations.invoke -private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ONE) - @State(Scope.Benchmark) internal class BigIntBenchmark { val kmNumber = BigIntField.number(Int.MAX_VALUE) val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE) - val largeKmNumber = BigIntField { number(11).pow(100_000) } + val largeKmNumber = BigIntField { number(11).pow(100_000UL) } val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) } val bigExponent = 50_000 @@ -59,7 +57,7 @@ internal class BigIntBenchmark { @Benchmark fun kmPower(blackhole: Blackhole) = BigIntField { - blackhole.consume(kmNumber.pow(bigExponent)) + blackhole.consume(kmNumber.pow(bigExponent.toULong())) } @Benchmark diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 0334e0466..49861b543 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -250,6 +250,21 @@ public interface Ring : Group, RingOperations { * neutral operation for multiplication */ public val one: T + + public fun T.pow(exponent: ULong): T = when { + this == zero && exponent > 0UL -> zero + this == one -> this + else -> powWithoutOptimization(exponent) + } + + private fun T.powWithoutOptimization(exponent: ULong): T = when (exponent) { + 0UL -> one + 1UL -> this + else -> { + val pre = powWithoutOptimization(exponent shr 1).let { it * it } + if (exponent and 1UL == 0UL) pre else pre * this + } + } } /** diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt index 5df89a385..05b73b49d 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.operations import space.kscience.kmath.testutils.RingVerifier +import kotlin.math.pow import kotlin.test.Test import kotlin.test.assertEquals @@ -21,6 +22,19 @@ internal class BigIntAlgebraTest { assertEquals(res, 1_000_000.toBigInt()) } + @Test + fun testKBigIntegerRingPow() { + BigIntField { + for (num in 0..5) + for (exponent in 0UL..10UL) + assertEquals( + num.toDouble().pow(exponent.toInt()).toLong().toBigInt(), + num.toBigInt().pow(exponent), + "$num ^ $exponent" + ) + } + } + @Test fun testKBigIntegerRingSum_100_000_000__100_000_000() { BigIntField { From d17a3ac6eff3d6c62e99af7e030010846afd413b Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Mon, 10 May 2021 18:24:13 +0300 Subject: [PATCH 318/393] Further optimization of power is added --- .../kotlin/space/kscience/kmath/operations/Algebra.kt | 1 + .../kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 49861b543..f7c021998 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -254,6 +254,7 @@ public interface Ring : Group, RingOperations { public fun T.pow(exponent: ULong): T = when { this == zero && exponent > 0UL -> zero this == one -> this + this == -one -> powWithoutOptimization(exponent % 2UL) else -> powWithoutOptimization(exponent) } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt index 05b73b49d..90cd29758 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt @@ -25,7 +25,7 @@ internal class BigIntAlgebraTest { @Test fun testKBigIntegerRingPow() { BigIntField { - for (num in 0..5) + for (num in -5..5) for (exponent in 0UL..10UL) assertEquals( num.toDouble().pow(exponent.toInt()).toLong().toBigInt(), From 3ad7f32ada115b279e00edc49f5e9ba7e63a834d Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Mon, 10 May 2021 18:41:40 +0300 Subject: [PATCH 319/393] Incorrect BigInt equality fixed --- .../kotlin/space/kscience/kmath/operations/BigInt.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index e74efa9ca..e81f1686d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -56,8 +56,7 @@ public class BigInt internal constructor( else -> sign * compareMagnitudes(magnitude, other.magnitude) } - public override fun equals(other: Any?): Boolean = - if (other is BigInt) compareTo(other) == 0 else error("Can't compare KBigInteger to a different type") + public override fun equals(other: Any?): Boolean = other is BigInt && compareTo(other) == 0 public override fun hashCode(): Int = magnitude.hashCode() + sign From 2da0648d73829396777066f970bf861e75410f01 Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Tue, 11 May 2021 01:40:45 +0300 Subject: [PATCH 320/393] Karatsuba added Incorrect equals fix test Incorrect overflow handling support --- .../space/kscience/kmath/operations/BigInt.kt | 46 +++++++++++++++---- .../kmath/operations/BigIntOperationsTest.kt | 25 +++++++++- 2 files changed, 61 insertions(+), 10 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index e81f1686d..c7079902b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -86,20 +86,23 @@ public class BigInt internal constructor( public operator fun times(b: BigInt): BigInt = when { this.sign == 0.toByte() -> ZERO b.sign == 0.toByte() -> ZERO -// TODO: Karatsuba + b.magnitude.size == 1 -> this * b.magnitude[0] * b.sign.toInt() + this.magnitude.size == 1 -> b * this.magnitude[0] * this.sign.toInt() else -> BigInt((this.sign * b.sign).toByte(), multiplyMagnitudes(this.magnitude, b.magnitude)) } public operator fun times(other: UInt): BigInt = when { sign == 0.toByte() -> ZERO other == 0U -> ZERO + other == 1U -> this else -> BigInt(sign, multiplyMagnitudeByUInt(magnitude, other)) } - public operator fun times(other: Int): BigInt = if (other > 0) - this * kotlin.math.abs(other).toUInt() - else - -this * kotlin.math.abs(other).toUInt() + public operator fun times(other: Int): BigInt = when { + other > 0 -> this * kotlin.math.abs(other).toUInt() + other != Int.MIN_VALUE -> -this * kotlin.math.abs(other).toUInt() + else -> times(other.toBigInt()) + } public operator fun div(other: UInt): BigInt = BigInt(this.sign, divideMagnitudeByUInt(this.magnitude, other)) @@ -237,6 +240,7 @@ public class BigInt internal constructor( public const val BASE_SIZE: Int = 32 public val ZERO: BigInt = BigInt(0, uintArrayOf()) public val ONE: BigInt = BigInt(1, uintArrayOf(1u)) + private const val KARATSUBA_THRESHOLD = 80 private val hexMapping: HashMap = hashMapOf( 0U to "0", 1U to "1", 2U to "2", 3U to "3", @@ -317,7 +321,16 @@ public class BigInt internal constructor( return stripLeadingZeros(result) } - private fun multiplyMagnitudes(mag1: Magnitude, mag2: Magnitude): Magnitude { + internal fun multiplyMagnitudes(mag1: Magnitude, mag2: Magnitude): Magnitude = when { + mag1.size + mag2.size < KARATSUBA_THRESHOLD || mag1.isEmpty() || mag2.isEmpty() -> naiveMultiplyMagnitudes( + mag1, + mag2 + ) + // TODO implement Fourier + else -> karatsubaMultiplyMagnitudes(mag1, mag2) + } + + internal fun naiveMultiplyMagnitudes(mag1: Magnitude, mag2: Magnitude): Magnitude { val resultLength = mag1.size + mag2.size val result = Magnitude(resultLength) @@ -336,6 +349,21 @@ public class BigInt internal constructor( return stripLeadingZeros(result) } + internal fun karatsubaMultiplyMagnitudes(mag1: Magnitude, mag2: Magnitude): Magnitude { + //https://en.wikipedia.org/wiki/Karatsuba_algorithm + val halfSize = min(mag1.size, mag2.size) / 2 + val x0 = mag1.sliceArray(0 until halfSize).toBigInt(1) + val x1 = mag1.sliceArray(halfSize until mag1.size).toBigInt(1) + val y0 = mag2.sliceArray(0 until halfSize).toBigInt(1) + val y1 = mag2.sliceArray(halfSize until mag2.size).toBigInt(1) + + val z0 = x0 * y0 + val z2 = x1 * y1 + val z1 = (x0 + x1) * (y1 + y0) - z0 - z2 + + return (z2.shl(2 * halfSize * BASE_SIZE) + z1.shl(halfSize * BASE_SIZE) + z0).magnitude + } + private fun divideMagnitudeByUInt(mag: Magnitude, x: UInt): Magnitude { val resultLength = mag.size val result = Magnitude(resultLength) @@ -426,7 +454,7 @@ private val hexChToInt: MutableMap = hashMapOf( public fun String.parseBigInteger(): BigInt? { val sign: Int val sPositive: String - + //TODO substring = O(n). Can be replaced by some drop that is O(1) when { this[0] == '+' -> { sign = +1 @@ -446,8 +474,10 @@ public fun String.parseBigInteger(): BigInt? { var digitValue = BigInt.ONE val sPositiveUpper = sPositive.uppercase() - if (sPositiveUpper.startsWith("0X")) { // hex representation + if (sPositiveUpper.startsWith("0X")) { + // hex representation val sHex = sPositiveUpper.substring(2) + // TODO optimize O(n2) -> O(n) for (ch in sHex.reversed()) { if (ch == '_') continue diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt index ae34dbc04..9f35f7a69 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt @@ -5,8 +5,9 @@ package space.kscience.kmath.operations -import kotlin.test.Test -import kotlin.test.assertEquals +import kotlin.random.Random +import kotlin.random.nextUInt +import kotlin.test.* @kotlin.ExperimentalUnsignedTypes class BigIntOperationsTest { @@ -150,6 +151,18 @@ class BigIntOperationsTest { assertEquals(prod, res) } + @Test + fun testKaratsuba() { + val x = uintArrayOf(12U, 345U) + val y = uintArrayOf(6U, 789U) + assertContentEquals(BigInt.naiveMultiplyMagnitudes(x, y), BigInt.karatsubaMultiplyMagnitudes(x, y)) + repeat(1000) { + val x1 = UIntArray(Random.nextInt(100, 1000)) { Random.nextUInt() } + val y1 = UIntArray(Random.nextInt(100, 1000)) { Random.nextUInt() } + assertContentEquals(BigInt.naiveMultiplyMagnitudes(x1, y1), BigInt.karatsubaMultiplyMagnitudes(x1, y1)) + } + } + @Test fun test_shr_20() { val x = 20.toBigInt() @@ -383,4 +396,12 @@ class BigIntOperationsTest { return assertEquals(res, x % mod) } + + @Test + fun testNotEqualsOtherTypeInstanceButButNotFails() = assertFalse(0.toBigInt().equals("")) + + @Test + fun testIntAbsOverflow() { + assertEquals((-Int.MAX_VALUE.toLong().toBigInt() - 1.toBigInt()) * 2, 2.toBigInt() * Int.MIN_VALUE) + } } From 74d14970b9e50e808c8901b8d2850ecd29f79ba1 Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Wed, 12 May 2021 00:58:27 +0300 Subject: [PATCH 321/393] empty string parsing fixed --- .../space/kscience/kmath/operations/BigInt.kt | 7 +++++- .../kmath/operations/BigIntConversionsTest.kt | 22 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index c7079902b..00b9f9fc2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -452,6 +452,7 @@ private val hexChToInt: MutableMap = hashMapOf( * Returns null if a valid number can not be read from a string */ public fun String.parseBigInteger(): BigInt? { + if (this.isEmpty()) return null val sign: Int val sPositive: String //TODO substring = O(n). Can be replaced by some drop that is O(1) @@ -473,15 +474,18 @@ public fun String.parseBigInteger(): BigInt? { var res = BigInt.ZERO var digitValue = BigInt.ONE val sPositiveUpper = sPositive.uppercase() + var isEmpty = true if (sPositiveUpper.startsWith("0X")) { // hex representation val sHex = sPositiveUpper.substring(2) + if (this.isEmpty()) return null // TODO optimize O(n2) -> O(n) for (ch in sHex.reversed()) { if (ch == '_') continue res += digitValue * (hexChToInt[ch] ?: return null) + isEmpty = false digitValue *= 16.toBigInt() } } else for (ch in sPositiveUpper.reversed()) { @@ -491,10 +495,11 @@ public fun String.parseBigInteger(): BigInt? { return null } res += digitValue * (ch.code - '0'.code) + isEmpty = false digitValue *= 10.toBigInt() } - return res * sign + return if (isEmpty) null else res * sign } public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer = diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt index a2832e531..1feaae808 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt @@ -7,9 +7,31 @@ package space.kscience.kmath.operations import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertNull @kotlin.ExperimentalUnsignedTypes class BigIntConversionsTest { + + @Test + fun emptyString() { + assertNull("".parseBigInteger()) + assertNull("+".parseBigInteger()) + assertNull("-".parseBigInteger()) + + assertNull("0x".parseBigInteger()) + assertNull("+0x".parseBigInteger()) + assertNull("-0x".parseBigInteger()) + + + assertNull("_".parseBigInteger()) + assertNull("+_".parseBigInteger()) + assertNull("-_".parseBigInteger()) + + assertNull("0x_".parseBigInteger()) + assertNull("+0x_".parseBigInteger()) + assertNull("-0x_".parseBigInteger()) + } + @Test fun testToString0x10() { val x = 0x10.toBigInt() From 9184bd55de46bcb16a5c33b8a02f604b592aff4a Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Wed, 12 May 2021 02:01:49 +0300 Subject: [PATCH 322/393] Parser optimization --- .../space/kscience/kmath/operations/BigInt.kt | 90 +++++++++++-------- 1 file changed, 55 insertions(+), 35 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 00b9f9fc2..ab05d079f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -441,11 +441,11 @@ public fun UIntArray.toBigInt(sign: Byte): BigInt { return BigInt(sign, copyOf()) } -private val hexChToInt: MutableMap = hashMapOf( - '0' to 0, '1' to 1, '2' to 2, '3' to 3, - '4' to 4, '5' to 5, '6' to 6, '7' to 7, - '8' to 8, '9' to 9, 'A' to 10, 'B' to 11, - 'C' to 12, 'D' to 13, 'E' to 14, 'F' to 15 +private val hexChToInt: MutableMap = hashMapOf( + '0' to 0U, '1' to 1U, '2' to 2U, '3' to 3U, + '4' to 4U, '5' to 5U, '6' to 6U, '7' to 7U, + '8' to 8U, '9' to 9U, 'A' to 10U, 'B' to 11U, + 'C' to 12U, 'D' to 13U, 'E' to 14U, 'F' to 15U ) /** @@ -454,52 +454,72 @@ private val hexChToInt: MutableMap = hashMapOf( public fun String.parseBigInteger(): BigInt? { if (this.isEmpty()) return null val sign: Int - val sPositive: String - //TODO substring = O(n). Can be replaced by some drop that is O(1) - when { - this[0] == '+' -> { + + val positivePartIndex = when (this[0]) { + '+' -> { sign = +1 - sPositive = this.substring(1) + 1 } - this[0] == '-' -> { + '-' -> { sign = -1 - sPositive = this.substring(1) + 1 } else -> { - sPositive = this sign = +1 + 0 } } - var res = BigInt.ZERO - var digitValue = BigInt.ONE - val sPositiveUpper = sPositive.uppercase() var isEmpty = true - if (sPositiveUpper.startsWith("0X")) { + return if (this.startsWith("0X", startIndex = positivePartIndex, ignoreCase = true)) { // hex representation - val sHex = sPositiveUpper.substring(2) - if (this.isEmpty()) return null - // TODO optimize O(n2) -> O(n) - for (ch in sHex.reversed()) { - if (ch == '_') continue - res += digitValue * (hexChToInt[ch] ?: return null) + val uInts = mutableListOf(0U) + var offset = 0 + fun addDigit(value: UInt) { + uInts[uInts.lastIndex] += value shl offset + offset += 4 + if (offset == 32) { + uInts.add(0U) + offset = 0 + } + } + + for (index in lastIndex downTo positivePartIndex + 2) { + when (val ch = this[index]) { + '_' -> continue + in '0'..'9' -> addDigit((ch - '0').toUInt()) + in 'A'..'F' -> addDigit((ch - 'A').toUInt() + 10U) + in 'a'..'f' -> addDigit((ch - 'a').toUInt() + 10U) + else -> return null + } isEmpty = false - digitValue *= 16.toBigInt() } - } else for (ch in sPositiveUpper.reversed()) { - // decimal representation - if (ch == '_') continue - if (ch !in '0'..'9') { - return null - } - res += digitValue * (ch.code - '0'.code) - isEmpty = false - digitValue *= 10.toBigInt() - } - return if (isEmpty) null else res * sign + while (uInts.isNotEmpty() && uInts.last() == 0U) + uInts.removeLast() + + if (isEmpty) null else BigInt(sign.toByte(), uInts.toUIntArray()) + } else { + // hex representation + var res = BigInt.ZERO + var digitValue = BigInt.ONE + for (index in lastIndex downTo positivePartIndex) { + val ch = this[index] + // decimal representation + if (ch == '_') continue + if (ch !in '0'..'9') { + return null + } + res += digitValue * (ch.code - '0'.code) + isEmpty = false + digitValue *= 10.toBigInt() + + } + + if (isEmpty) null else res * sign + } } public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer = From b4e47494fcf6683d14d523aaaba34e33da592c3c Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Wed, 12 May 2021 04:42:17 +0300 Subject: [PATCH 323/393] Parsing of decimal values takes 9 immediately digits but not 1. --- .../kmath/benchmarks/BigIntBenchmark.kt | 25 ++++++++-- .../space/kscience/kmath/operations/BigInt.kt | 47 ++++++++++--------- .../kmath/operations/BigIntConversionsTest.kt | 8 +++- 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index 33c659fca..639eaacf3 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -10,10 +10,7 @@ import kotlinx.benchmark.Blackhole import org.openjdk.jmh.annotations.Benchmark import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State -import space.kscience.kmath.operations.BigInt -import space.kscience.kmath.operations.BigIntField -import space.kscience.kmath.operations.JBigIntegerField -import space.kscience.kmath.operations.invoke +import space.kscience.kmath.operations.* @State(Scope.Benchmark) @@ -64,4 +61,24 @@ internal class BigIntBenchmark { fun jvmPower(blackhole: Blackhole) = JBigIntegerField { blackhole.consume(jvmNumber.pow(bigExponent)) } + + @Benchmark + fun kmParsing16(blackhole: Blackhole) = JBigIntegerField { + blackhole.consume("0x7f57ed8b89c29a3b9a85c7a5b84ca3929c7b7488593".parseBigInteger()) + } + + @Benchmark + fun kmParsing10(blackhole: Blackhole) = JBigIntegerField { + blackhole.consume("236656783929183747565738292847574838922010".parseBigInteger()) + } + + @Benchmark + fun jvmParsing10(blackhole: Blackhole) = JBigIntegerField { + blackhole.consume("236656783929183747565738292847574838922010".toBigInteger(10)) + } + + @Benchmark + fun jvmParsing16(blackhole: Blackhole) = JBigIntegerField { + blackhole.consume("7f57ed8b89c29a3b9a85c7a5b84ca3929c7b7488593".toBigInteger(16)) + } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index ab05d079f..780a4591d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -441,13 +441,6 @@ public fun UIntArray.toBigInt(sign: Byte): BigInt { return BigInt(sign, copyOf()) } -private val hexChToInt: MutableMap = hashMapOf( - '0' to 0U, '1' to 1U, '2' to 2U, '3' to 3U, - '4' to 4U, '5' to 5U, '6' to 6U, '7' to 7U, - '8' to 8U, '9' to 9U, 'A' to 10U, 'B' to 11U, - 'C' to 12U, 'D' to 13U, 'E' to 14U, 'F' to 15U -) - /** * Returns null if a valid number can not be read from a string */ @@ -475,7 +468,7 @@ public fun String.parseBigInteger(): BigInt? { return if (this.startsWith("0X", startIndex = positivePartIndex, ignoreCase = true)) { // hex representation - val uInts = mutableListOf(0U) + val uInts = ArrayList(length).apply { add(0U) } var offset = 0 fun addDigit(value: UInt) { uInts[uInts.lastIndex] += value shl offset @@ -502,22 +495,34 @@ public fun String.parseBigInteger(): BigInt? { if (isEmpty) null else BigInt(sign.toByte(), uInts.toUIntArray()) } else { - // hex representation - var res = BigInt.ZERO - var digitValue = BigInt.ONE - for (index in lastIndex downTo positivePartIndex) { - val ch = this[index] - // decimal representation - if (ch == '_') continue - if (ch !in '0'..'9') { - return null - } - res += digitValue * (ch.code - '0'.code) - isEmpty = false - digitValue *= 10.toBigInt() + // decimal representation + val positivePart = buildList(length) { + for (index in positivePartIndex until length) + when (val a = this@parseBigInteger[index]) { + '_' -> continue + in '0'..'9' -> add(a) + else -> return null + } } + val offset = positivePart.size % 9 + isEmpty = offset == 0 + + fun parseUInt(fromIndex: Int, toIndex: Int): UInt? { + var res = 0U + for (i in fromIndex until toIndex) { + res = res * 10U + (positivePart[i].digitToIntOrNull()?.toUInt() ?: return null) + } + return res + } + + var res = parseUInt(0, offset)?.toBigInt() ?: return null + + for (index in offset..positivePart.lastIndex step 9) { + isEmpty = false + res = res * 1_000_000_000U + (parseUInt(index, index + 9) ?: return null).toBigInt() + } if (isEmpty) null else res * sign } } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt index 1feaae808..85f368f3e 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt @@ -13,7 +13,7 @@ import kotlin.test.assertNull class BigIntConversionsTest { @Test - fun emptyString() { + fun testEmptyString() { assertNull("".parseBigInteger()) assertNull("+".parseBigInteger()) assertNull("-".parseBigInteger()) @@ -38,6 +38,12 @@ class BigIntConversionsTest { assertEquals("0x10", x.toString()) } + @Test + fun testUnderscores() { + assertEquals("0x10", "0x_1_0_".parseBigInteger().toString()) + assertEquals("0xa", "_1_0_".parseBigInteger().toString()) + } + @Test fun testToString0x17ffffffd() { val x = 0x17ffffffdL.toBigInt() From ed86a31c50d7d6b3890342fb2652ffdba4630fb0 Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Wed, 12 May 2021 04:58:48 +0300 Subject: [PATCH 324/393] Placing pow outside the Ring interface. --- .../kscience/kmath/operations/Algebra.kt | 26 +++++++++---------- .../space/kscience/kmath/operations/BigInt.kt | 2 ++ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index f7c021998..645e60c29 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -250,21 +250,21 @@ public interface Ring : Group, RingOperations { * neutral operation for multiplication */ public val one: T +} - public fun T.pow(exponent: ULong): T = when { - this == zero && exponent > 0UL -> zero - this == one -> this - this == -one -> powWithoutOptimization(exponent % 2UL) - else -> powWithoutOptimization(exponent) - } +public fun Ring.pow(base: T, exponent: ULong): T = when { + this == zero && exponent > 0UL -> zero + this == one -> base + this == -one -> powWithoutOptimization(base, exponent % 2UL) + else -> powWithoutOptimization(base, exponent) +} - private fun T.powWithoutOptimization(exponent: ULong): T = when (exponent) { - 0UL -> one - 1UL -> this - else -> { - val pre = powWithoutOptimization(exponent shr 1).let { it * it } - if (exponent and 1UL == 0UL) pre else pre * this - } +private fun Ring.powWithoutOptimization(base: T, exponent: ULong): T = when (exponent) { + 0UL -> one + 1UL -> base + else -> { + val pre = powWithoutOptimization(base, exponent shr 1).let { it * it } + if (exponent and 1UL == 0UL) pre else pre * base } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 780a4591d..88c952928 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -98,6 +98,8 @@ public class BigInt internal constructor( else -> BigInt(sign, multiplyMagnitudeByUInt(magnitude, other)) } + public fun pow(other: ULong): BigInt = BigIntField { pow(this@BigInt, other) } + public operator fun times(other: Int): BigInt = when { other > 0 -> this * kotlin.math.abs(other).toUInt() other != Int.MIN_VALUE -> -this * kotlin.math.abs(other).toUInt() From ded01251d1e94af4edf315c3d5ad70dce6b06ee0 Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Wed, 12 May 2021 11:05:42 +0300 Subject: [PATCH 325/393] Karatsuba enhancement --- .../kotlin/space/kscience/kmath/operations/BigInt.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 88c952928..be73e274a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -324,10 +324,8 @@ public class BigInt internal constructor( } internal fun multiplyMagnitudes(mag1: Magnitude, mag2: Magnitude): Magnitude = when { - mag1.size + mag2.size < KARATSUBA_THRESHOLD || mag1.isEmpty() || mag2.isEmpty() -> naiveMultiplyMagnitudes( - mag1, - mag2 - ) + mag1.size + mag2.size < KARATSUBA_THRESHOLD || mag1.isEmpty() || mag2.isEmpty() -> + naiveMultiplyMagnitudes(mag1, mag2) // TODO implement Fourier else -> karatsubaMultiplyMagnitudes(mag1, mag2) } @@ -361,7 +359,7 @@ public class BigInt internal constructor( val z0 = x0 * y0 val z2 = x1 * y1 - val z1 = (x0 + x1) * (y1 + y0) - z0 - z2 + val z1 = (x0 - x1) * (y1 - y0) + z0 + z2 return (z2.shl(2 * halfSize * BASE_SIZE) + z1.shl(halfSize * BASE_SIZE) + z0).magnitude } From 1e71f29d5e64a5c933630f892fab29cdfbd36e63 Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Wed, 12 May 2021 13:59:41 +0300 Subject: [PATCH 326/393] Large addition tests added --- .../space/kscience/kmath/benchmarks/BigIntBenchmark.kt | 10 ++++++++++ .../kotlin/space/kscience/kmath/operations/BigInt.kt | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index 639eaacf3..d3262379f 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -32,6 +32,16 @@ internal class BigIntBenchmark { blackhole.consume(jvmNumber + jvmNumber + jvmNumber) } + @Benchmark + fun kmAddLarge(blackhole: Blackhole) = BigIntField { + blackhole.consume(largeKmNumber + largeKmNumber + largeKmNumber) + } + + @Benchmark + fun jvmAddLarge(blackhole: Blackhole) = JBigIntegerField { + blackhole.consume(largeJvmNumber + largeJvmNumber + largeJvmNumber) + } + @Benchmark fun kmMultiply(blackhole: Blackhole) = BigIntField { blackhole.consume(kmNumber * kmNumber * kmNumber) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index be73e274a..605dfd265 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -281,7 +281,7 @@ public class BigInt internal constructor( } result[i] = (res and BASE).toUInt() - carry = (res shr BASE_SIZE) + carry = res shr BASE_SIZE } result[resultLength - 1] = carry.toUInt() From 8443fac4ae4df746f26a1dd444be1ef194d7baa5 Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Wed, 12 May 2021 14:10:32 +0300 Subject: [PATCH 327/393] UInt can be used in exponent (in pow) now. --- .../kotlin/space/kscience/kmath/operations/Algebra.kt | 2 ++ .../kotlin/space/kscience/kmath/operations/BigInt.kt | 1 + .../space/kscience/kmath/operations/BigIntAlgebraTest.kt | 8 +++++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 645e60c29..a23dc427c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -259,6 +259,8 @@ public fun Ring.pow(base: T, exponent: ULong): T = when { else -> powWithoutOptimization(base, exponent) } +public fun Ring.pow(base: T, exponent: UInt): T = pow(base, exponent.toULong()) + private fun Ring.powWithoutOptimization(base: T, exponent: ULong): T = when (exponent) { 0UL -> one 1UL -> base diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 605dfd265..45161149c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -99,6 +99,7 @@ public class BigInt internal constructor( } public fun pow(other: ULong): BigInt = BigIntField { pow(this@BigInt, other) } + public fun pow(other: UInt): BigInt = BigIntField { pow(this@BigInt, other) } public operator fun times(other: Int): BigInt = when { other > 0 -> this * kotlin.math.abs(other).toUInt() diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt index 90cd29758..abc88934c 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt @@ -26,12 +26,18 @@ internal class BigIntAlgebraTest { fun testKBigIntegerRingPow() { BigIntField { for (num in -5..5) - for (exponent in 0UL..10UL) + for (exponent in 0U..10U) { + assertEquals( + num.toDouble().pow(exponent.toInt()).toLong().toBigInt(), + num.toBigInt().pow(exponent.toULong()), + "$num ^ $exponent" + ) assertEquals( num.toDouble().pow(exponent.toInt()).toLong().toBigInt(), num.toBigInt().pow(exponent), "$num ^ $exponent" ) + } } } From e5f3ee75be375f457c342ab5fc02ff0f324c6490 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 12 May 2021 19:40:10 +0100 Subject: [PATCH 328/393] tensors readme fix --- README.md | 7 ++++--- kmath-tensors/README.md | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3b4387c1b..c3def902b 100644 --- a/README.md +++ b/README.md @@ -247,9 +247,10 @@ One can still use generic algebras though. > **Maturity**: PROTOTYPE > > **Features:** -> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) -> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. -> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. +> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Interface for basic linear algebra operations on tensors (plus, dot, etc.) +> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Interface for advanced linear algebra operations like LU decomposition, SVD, etc. +> - [tensor algebra over Double](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s +> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting for tensors over `Double`'s.
diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 7ece44217..586bb8ac6 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -2,10 +2,10 @@ Common linear algebra operations on tensors. - - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) - - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. - - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. - + - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Interface for basic linear algebra operations on tensors (plus, dot, etc.) + - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Interface for advanced linear algebra operations like LU decomposition, SVD, etc. + - [tensor algebra over Double](src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s + - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting for tensors over `Double`'s. ## Artifact: From d721c4b5976072dae740243b2f1cefee5fcbe2b2 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Wed, 12 May 2021 19:43:08 +0100 Subject: [PATCH 329/393] typo found --- README.md | 2 +- kmath-tensors/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c3def902b..519472a69 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,7 @@ One can still use generic algebras though. > **Features:** > - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Interface for basic linear algebra operations on tensors (plus, dot, etc.) > - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Interface for advanced linear algebra operations like LU decomposition, SVD, etc. -> - [tensor algebra over Double](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s +> - [tensor algebra over Double](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s. > - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting for tensors over `Double`'s.
diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 586bb8ac6..affdad665 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -4,7 +4,7 @@ Common linear algebra operations on tensors. - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Interface for basic linear algebra operations on tensors (plus, dot, etc.) - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Interface for advanced linear algebra operations like LU decomposition, SVD, etc. - - [tensor algebra over Double](src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s + - [tensor algebra over Double](src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s. - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting for tensors over `Double`'s. ## Artifact: From 97c4b817173637818f1b496580afc688af8825d2 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 13 May 2021 11:02:20 +0300 Subject: [PATCH 330/393] Introduce PerformancePitfall annotation --- CHANGELOG.md | 1 + LICENSE | 201 ------------------ .../space/kscience/kmath/data/ColumnarData.kt | 2 + .../kscience/kmath/data/XYColumnarData.kt | 2 + .../kmath/linear/BufferedLinearSpace.kt | 3 + .../space/kscience/kmath/misc/annotations.kt | 12 ++ .../space/kscience/kmath/nd/BufferND.kt | 2 + .../space/kscience/kmath/nd/Structure1D.kt | 21 +- .../space/kscience/kmath/nd/Structure2D.kt | 8 +- .../space/kscience/kmath/nd/StructureND.kt | 4 + .../kmath/linear/DoubleLUSolverTest.kt | 2 + .../space/kscience/kmath/linear/MatrixTest.kt | 2 + .../kmath/structures/NumberNDFieldTest.kt | 2 + .../kmath/structures/LazyStructureND.kt | 2 + .../kscience/kmath/ejml/EjmlMatrixTest.kt | 2 + .../space/kscience/kmath/real/RealMatrix.kt | 4 + .../kaceince/kmath/real/DoubleMatrixTest.kt | 2 + .../kscience/kmath/jupyter/KMathJupyter.kt | 4 +- .../kscience/kmath/nd4j/Nd4jArrayStructure.kt | 2 + .../kmath/tensors/core/BufferedTensor.kt | 6 +- .../kmath/viktor/ViktorStructureND.kt | 2 + 21 files changed, 75 insertions(+), 211 deletions(-) delete mode 100644 LICENSE diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fba361d5..286be25e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Integration for any Field element - Extended operations for ND4J fields - Jupyter Notebook integration module (kmath-jupyter) +- `@PerformancePitfall` annotation to mark possibly slow API ### Changed - Exponential operations merged with hyperbolic functions diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt index abbb46583..febf615a8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.data +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D @@ -25,6 +26,7 @@ public interface ColumnarData { * A zero-copy method to represent a [Structure2D] as a two-column x-y data. * There could more than two columns in the structure. */ +@OptIn(PerformancePitfall::class) @UnstableKMathAPI public fun Structure2D.asColumnarData(mapping: Map): ColumnarData { require(shape[1] >= mapping.maxOf { it.value }) { "Column index out of bounds" } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt index 663908e90..56bb59826 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.data +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D @@ -49,6 +50,7 @@ public fun XYColumnarData(x: Buffer, y: Buffer): XYColum * A zero-copy method to represent a [Structure2D] as a two-column x-y data. * There could more than two columns in the structure. */ +@OptIn(PerformancePitfall::class) @UnstableKMathAPI public fun Structure2D.asXYData(xIndex: Int = 0, yIndex: Int = 1): XYColumnarData { require(shape[1] >= max(xIndex, yIndex)) { "Column index out of bounds" } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt index 62d2408e3..9b4451a62 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.linear +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.invoke @@ -50,6 +51,7 @@ public class BufferedLinearSpace>( this } + @OptIn(PerformancePitfall::class) override fun Matrix.dot(other: Matrix): Matrix { require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" } return elementAlgebra { @@ -67,6 +69,7 @@ public class BufferedLinearSpace>( } } + @OptIn(PerformancePitfall::class) override fun Matrix.dot(vector: Point): Point { require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" } return elementAlgebra { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt index 7f53d96ce..18718de97 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt @@ -15,3 +15,15 @@ package space.kscience.kmath.misc @Retention(value = AnnotationRetention.BINARY) @RequiresOptIn("This API is unstable and could change in future", RequiresOptIn.Level.WARNING) public annotation class UnstableKMathAPI + +/** + * Marks API which could cause performance problems. The code, marked by this API is not necessary slow, but could cause + * slow-down in some cases. Refer to the documentation and benchmark it to be sure. + */ +@MustBeDocumented +@Retention(value = AnnotationRetention.BINARY) +@RequiresOptIn( + "Refer to the documentation to use this API in performance-critical code", + RequiresOptIn.Level.WARNING +) +public annotation class PerformancePitfall diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt index 1f608f478..425808aeb 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.MutableBuffer @@ -32,6 +33,7 @@ public open class BufferND( override val shape: IntArray get() = strides.shape + @PerformancePitfall override fun elements(): Sequence> = strides.indices().map { it to this[it] } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 8ea6d0f02..cc0528793 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.asMutableBuffer @@ -46,6 +47,8 @@ private value class Structure1DWrapper(val structure: StructureND) : Struc override val size: Int get() = structure.shape[0] override operator fun get(index: Int): T = structure[index] + + @PerformancePitfall override fun elements(): Sequence> = structure.elements() } @@ -55,6 +58,8 @@ private value class Structure1DWrapper(val structure: StructureND) : Struc private class MutableStructure1DWrapper(val structure: MutableStructureND) : MutableStructure1D { override val shape: IntArray get() = structure.shape override val size: Int get() = structure.shape[0] + + @PerformancePitfall override fun elements(): Sequence> = structure.elements() override fun get(index: Int): T = structure[index] @@ -62,8 +67,8 @@ private class MutableStructure1DWrapper(val structure: MutableStructureND) structure[intArrayOf(index)] = value } - override fun copy(): MutableBuffer = - structure.elements().map { it.second }.toMutableList().asMutableBuffer() + @PerformancePitfall + override fun copy(): MutableBuffer = structure.elements().map { it.second }.toMutableList().asMutableBuffer() } @@ -75,8 +80,10 @@ private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D { override val shape: IntArray get() = intArrayOf(buffer.size) override val size: Int get() = buffer.size - override fun elements(): Sequence> = - buffer.asSequence().mapIndexed { index, value -> intArrayOf(index) to value } + @PerformancePitfall + override fun elements(): Sequence> = buffer.asSequence().mapIndexed { index, value -> + intArrayOf(index) to value + } override operator fun get(index: Int): T = buffer[index] } @@ -85,8 +92,10 @@ internal class MutableBuffer1DWrapper(val buffer: MutableBuffer) : Mutable override val shape: IntArray get() = intArrayOf(buffer.size) override val size: Int get() = buffer.size - override fun elements(): Sequence> = - buffer.asSequence().mapIndexed { index, value -> intArrayOf(index) to value } + @PerformancePitfall + override fun elements(): Sequence> = buffer.asSequence().mapIndexed { index, value -> + intArrayOf(index) to value + } override operator fun get(index: Int): T = buffer[index] override fun set(index: Int, value: T) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 28ae07a3c..8dce4ad6b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -5,10 +5,11 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.VirtualBuffer import space.kscience.kmath.structures.MutableListBuffer +import space.kscience.kmath.structures.VirtualBuffer import kotlin.jvm.JvmInline import kotlin.reflect.KClass @@ -33,12 +34,14 @@ public interface Structure2D : StructureND { /** * The buffer of rows of this structure. It gets elements from the structure dynamically. */ + @PerformancePitfall public val rows: List> get() = List(rowNum) { i -> VirtualBuffer(colNum) { j -> get(i, j) } } /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ + @PerformancePitfall public val columns: List> get() = List(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } } @@ -80,12 +83,14 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { /** * The buffer of rows of this structure. It gets elements from the structure dynamically. */ + @PerformancePitfall override val rows: List> get() = List(rowNum) { i -> MutableBuffer1DWrapper(MutableListBuffer(colNum) { j -> get(i, j) })} /** * The buffer of columns of this structure. It gets elements from the structure dynamically. */ + @PerformancePitfall override val columns: List> get() = List(colNum) { j -> MutableBuffer1DWrapper(MutableListBuffer(rowNum) { i -> get(i, j) }) } } @@ -105,6 +110,7 @@ private value class Structure2DWrapper(val structure: StructureND) : Struc @UnstableKMathAPI override fun getFeature(type: KClass): F? = structure.getFeature(type) + @PerformancePitfall override fun elements(): Sequence> = structure.elements() } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index a3331d71a..b9f1a063a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory @@ -48,6 +49,7 @@ public interface StructureND { * * @return the lazy sequence of pairs of indices to values. */ + @PerformancePitfall public fun elements(): Sequence> /** @@ -61,6 +63,7 @@ public interface StructureND { /** * Indicates whether some [StructureND] is equal to another one. */ + @PerformancePitfall public fun contentEquals(st1: StructureND, st2: StructureND): Boolean { if (st1 === st2) return true @@ -169,6 +172,7 @@ public interface MutableStructureND : StructureND { /** * Transform a structure element-by element in place. */ +@OptIn(PerformancePitfall::class) public inline fun MutableStructureND.mapInPlace(action: (IntArray, T) -> T): Unit = elements().forEach { (index, oldValue) -> this[index] = action(index, oldValue) } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt index ebbbbe392..2d2a0952b 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt @@ -5,12 +5,14 @@ package space.kscience.kmath.linear +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue +@OptIn(PerformancePitfall::class) fun assertMatrixEquals(expected: StructureND, actual: StructureND) { assertTrue { StructureND.contentEquals(expected, actual) } } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt index 250fa3433..170f9caf4 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.linear +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.as2D @@ -13,6 +14,7 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue @UnstableKMathAPI +@OptIn(PerformancePitfall::class) @Suppress("UNUSED_VARIABLE") class MatrixTest { @Test diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt index 99743d879..57393fadd 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.structures import space.kscience.kmath.linear.LinearSpace +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.invoke @@ -74,6 +75,7 @@ class NumberNDFieldTest { } object L2Norm : Norm, Double> { + @OptIn(PerformancePitfall::class) override fun norm(arg: StructureND): Double = kotlin.math.sqrt(arg.elements().sumOf { it.second.toDouble() }) } diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt index e2ecb4b2f..1cd16054a 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt @@ -7,6 +7,7 @@ package space.kscience.kmath.structures import kotlinx.coroutines.* import space.kscience.kmath.coroutines.Math +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.DefaultStrides import space.kscience.kmath.nd.StructureND @@ -24,6 +25,7 @@ public class LazyStructureND( public suspend fun await(index: IntArray): T = deferred(index).await() public override operator fun get(index: IntArray): T = runBlocking { deferred(index).await() } + @OptIn(PerformancePitfall::class) public override fun elements(): Sequence> { val strides = DefaultStrides(shape) val res = runBlocking { strides.indices().toList().map { index -> index to await(index) } } diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt index 485c53c38..50675bdac 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -12,12 +12,14 @@ import org.ejml.dense.row.factory.DecompositionFactory_DDRM import space.kscience.kmath.linear.DeterminantFeature import space.kscience.kmath.linear.LupDecompositionFeature import space.kscience.kmath.linear.getFeature +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import kotlin.random.Random import kotlin.random.asJavaRandom import kotlin.test.* +@OptIn(PerformancePitfall::class) fun assertMatrixEquals(expected: StructureND, actual: StructureND) { assertTrue { StructureND.contentEquals(expected, actual) } } diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt index c4656dd8a..8023236ea 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt @@ -3,9 +3,13 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:OptIn(PerformancePitfall::class) +@file:Suppress("unused") + package space.kscience.kmath.real import space.kscience.kmath.linear.* +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.Buffer diff --git a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt index 84e604b18..b3e129c2e 100644 --- a/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/kaceince/kmath/real/DoubleMatrixTest.kt @@ -7,6 +7,7 @@ package kaceince.kmath.real import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.matrix +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import space.kscience.kmath.real.* @@ -15,6 +16,7 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue +@OptIn(PerformancePitfall::class) fun assertMatrixEquals(expected: StructureND, actual: StructureND) { assertTrue { StructureND.contentEquals(expected, actual) } } diff --git a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt index 78b25af47..f3d553f2e 100644 --- a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt +++ b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt @@ -8,11 +8,12 @@ import org.jetbrains.kotlinx.jupyter.api.DisplayResult import org.jetbrains.kotlinx.jupyter.api.HTML import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration -import space.kscience.kmath.expressions.MST import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer import space.kscience.kmath.ast.rendering.renderWithStringBuilder import space.kscience.kmath.complex.Complex +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.operations.GroupOperations import space.kscience.kmath.operations.RingOperations @@ -55,6 +56,7 @@ internal class KMathJupyter : JupyterIntegration() { } } + @OptIn(PerformancePitfall::class) override fun Builder.onLoaded() { import( "space.kscience.kmath.ast.*", diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt index 79db86fcc..d37c91cb6 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.MutableStructureND import space.kscience.kmath.nd.StructureND @@ -24,6 +25,7 @@ public sealed class Nd4jArrayStructure : MutableStructureND { internal abstract fun elementsIterator(): Iterator> internal fun indicesIterator(): Iterator = ndArray.indicesIterator() + @PerformancePitfall public override fun elements(): Sequence> = Sequence(::elementsIterator) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 858532abc..315dc4505 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,7 +1,8 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.Strides -import space.kscience.kmath.structures.* +import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.internal.TensorLinearStructure @@ -32,7 +33,8 @@ public open class BufferedTensor internal constructor( mutableBuffer[bufferStart + linearStructure.offset(index)] = value } + @PerformancePitfall override fun elements(): Sequence> = linearStructure.indices().map { - it to this[it] + it to get(it) } } diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt index dc1b45f5d..b7abf4304 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.viktor import org.jetbrains.bio.viktor.F64Array +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleField @@ -23,6 +24,7 @@ public class ViktorStructureND(public val f64Buffer: F64Array) : MutableStructur f64Buffer.set(*index, value = value) } + @PerformancePitfall public override fun elements(): Sequence> = DefaultStrides(shape).indices().map { it to get(it) } } From f5289abdc3e6c636ff2411f04141eddd4847a5f8 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 13 May 2021 11:09:49 +0300 Subject: [PATCH 331/393] Introduce PerformancePitfall annotation --- kmath-core/api/kmath-core.api | 3 +++ .../commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt | 2 ++ .../kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt | 4 +--- .../kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt | 4 +--- .../space/kscience/kmath/histogram/IndexedHistogramSpace.kt | 5 ++--- .../kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 2 ++ .../kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt | 4 +++- .../space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt | 2 ++ .../space/kscience/kmath/tensors/core/TestDoubleTensor.kt | 2 ++ 9 files changed, 18 insertions(+), 10 deletions(-) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 7dd459104..14bc70a2a 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -674,6 +674,9 @@ public final class space/kscience/kmath/misc/CumulativeKt { public static final fun cumulativeSumOfLong (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; } +public abstract interface annotation class space/kscience/kmath/misc/PerformancePitfall : java/lang/annotation/Annotation { +} + public final class space/kscience/kmath/misc/StringSymbol : space/kscience/kmath/misc/Symbol { public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/misc/StringSymbol; public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 8dce4ad6b..5b8183699 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -59,6 +59,7 @@ public interface Structure2D : StructureND { return get(index[0], index[1]) } + @PerformancePitfall override fun elements(): Sequence> = sequence { for (i in 0 until rowNum) for (j in 0 until colNum) yield(intArrayOf(i, j) to get(i, j)) @@ -134,6 +135,7 @@ private class MutableStructure2DWrapper(val structure: MutableStructureND) structure[intArrayOf(i, j)] = value } + @PerformancePitfall override fun elements(): Sequence> = structure.elements() override fun equals(other: Any?): Boolean = false diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt index 3604fda31..2a4837ee0 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt @@ -7,16 +7,14 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.GroupElement import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import kotlin.math.sqrt @OptIn(UnstableKMathAPI::class) -public interface Vector2D : Point, Vector, GroupElement { +public interface Vector2D : Point, Vector{ public val x: Double public val y: Double - public override val context: Euclidean2DSpace get() = Euclidean2DSpace public override val size: Int get() = 2 public override operator fun get(index: Int): Double = when (index) { diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt index 8643b2dbb..37e7d2cb2 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt @@ -7,17 +7,15 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.GroupElement import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import kotlin.math.sqrt @OptIn(UnstableKMathAPI::class) -public interface Vector3D : Point, Vector, GroupElement { +public interface Vector3D : Point, Vector { public val x: Double public val y: Double public val z: Double - public override val context: Euclidean3DSpace get() = Euclidean3DSpace public override val size: Int get() = 3 public override operator fun get(index: Int): Double = when (index) { diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt index 818d81ab0..e5f6830c5 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/IndexedHistogramSpace.kt @@ -12,7 +12,6 @@ import space.kscience.kmath.nd.FieldND import space.kscience.kmath.nd.Strides import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.Group -import space.kscience.kmath.operations.GroupElement import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke @@ -26,9 +25,9 @@ public data class DomainBin>( @OptIn(UnstableKMathAPI::class) public class IndexedHistogram, V : Any>( - override val context: IndexedHistogramSpace, + public val context: IndexedHistogramSpace, public val values: StructureND, -) : Histogram>, GroupElement, IndexedHistogramSpace> { +) : Histogram> { override fun get(point: Point): Bin? { val index = context.getIndex(point) ?: return null diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index 0205f1c87..3cac44c47 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -10,6 +10,7 @@ import org.nd4j.linalg.api.ops.impl.scalar.Pow import org.nd4j.linalg.api.ops.impl.transforms.strict.* import org.nd4j.linalg.factory.Nd4j import org.nd4j.linalg.ops.transforms.Transforms +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* @@ -52,6 +53,7 @@ public interface Nd4jArrayAlgebra> : AlgebraND { return struct } + @PerformancePitfall public override fun StructureND.map(transform: C.(T) -> T): Nd4jArrayStructure { val newStruct = ndArray.dup().wrap() newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) } diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt index b6c524cc6..c80a1d771 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.factory.Nd4j +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.invoke import kotlin.math.PI @@ -14,6 +15,7 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue import kotlin.test.fail +@OptIn(PerformancePitfall::class) internal class Nd4jArrayAlgebraTest { @Test fun testProduce() { @@ -28,7 +30,7 @@ internal class Nd4jArrayAlgebraTest { @Test fun testMap() { - val res = with(IntNd4jArrayRing(intArrayOf(2, 2))) { one.map() { it + it * 2 } } + val res = with(IntNd4jArrayRing(intArrayOf(2, 2))) { one.map { it + it * 2 } } val expected = (Nd4j.create(2, 2) ?: fail()).asIntStructure() expected[intArrayOf(0, 0)] = 3 expected[intArrayOf(0, 1)] = 3 diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt index d59e04194..bdfec2ba6 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.factory.Nd4j +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.get import kotlin.test.Test import kotlin.test.assertEquals @@ -13,6 +14,7 @@ import kotlin.test.assertNotEquals import kotlin.test.fail internal class Nd4jArrayStructureTest { + @OptIn(PerformancePitfall::class) @Test fun testElements() { val nd = Nd4j.create(doubleArrayOf(1.0, 2.0, 3.0))!! diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index a6c6a7618..a176abdd4 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.DefaultStrides import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.nd.as1D @@ -24,6 +25,7 @@ internal class TestDoubleTensor { assertEquals(tensor.value(), value) } + @OptIn(PerformancePitfall::class) @Test fun testStrides() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) From feb5743f58616af3c46917ce098c63778191e5db Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 13 May 2021 11:10:59 +0300 Subject: [PATCH 332/393] Change signature of one of integrate helpers --- .../kscience/kmath/commons/integration/IntegrationTest.kt | 6 +++--- .../space/kscience/kmath/integration/UnivariateIntegrand.kt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt index 9d475d04d..97dc94d1d 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt @@ -19,16 +19,16 @@ internal class IntegrationTest { @Test fun simpson() { - val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function) + val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function = function) assertTrue { abs(res) < 1e-3 } } @Test fun customSimpson() { - val res = CMIntegrator.simpson().integrate(0.0..PI, function) { + val res = CMIntegrator.simpson().integrate(0.0..PI, { targetRelativeAccuracy = 1e-4 targetAbsoluteAccuracy = 1e-4 - } + }, function) assertTrue { abs(res - 2) < 1e-3 } assertTrue { abs(res - 2) > 1e-12 } } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index bcd5005c4..51ea57a33 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -57,8 +57,8 @@ public fun UnivariateIntegrator.integrate( @UnstableKMathAPI public fun UnivariateIntegrator.integrate( range: ClosedRange, + featureBuilder: MutableList.() -> Unit = {}, function: (Double) -> Double, - featureBuilder: (MutableList.() -> Unit) = {}, ): Double { //TODO use dedicated feature builder class instead or add extensions to MutableList val features = buildList { From 1e945389314cf8d3072f919f5c18afd9a4dcca4d Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Thu, 13 May 2021 13:11:20 +0300 Subject: [PATCH 333/393] Unstable API annotation added + inconsistent docs fix + unnecessary BigIntField usage removed --- .../kmath/benchmarks/BigIntBenchmark.kt | 5 +++- .../kscience/kmath/operations/Algebra.kt | 5 +++- .../space/kscience/kmath/operations/BigInt.kt | 3 ++ .../kmath/operations/OptionalOperations.kt | 2 +- .../kmath/operations/BigIntAlgebraTest.kt | 30 +++++++++---------- 5 files changed, 27 insertions(+), 18 deletions(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index d3262379f..21b097609 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -10,16 +10,19 @@ import kotlinx.benchmark.Blackhole import org.openjdk.jmh.annotations.Benchmark import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* +import java.math.BigInteger +@UnstableKMathAPI @State(Scope.Benchmark) internal class BigIntBenchmark { val kmNumber = BigIntField.number(Int.MAX_VALUE) val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE) val largeKmNumber = BigIntField { number(11).pow(100_000UL) } - val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) } + val largeJvmNumber: BigInteger = JBigIntegerField { number(11).pow(100_000) } val bigExponent = 50_000 @Benchmark diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index a23dc427c..8881ae93c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.operations import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI /** * Stub for DSL the [Algebra] is. @@ -247,11 +248,12 @@ public interface RingOperations : GroupOperations { */ public interface Ring : Group, RingOperations { /** - * neutral operation for multiplication + * The neutral element of multiplication */ public val one: T } +@UnstableKMathAPI public fun Ring.pow(base: T, exponent: ULong): T = when { this == zero && exponent > 0UL -> zero this == one -> base @@ -259,6 +261,7 @@ public fun Ring.pow(base: T, exponent: ULong): T = when { else -> powWithoutOptimization(base, exponent) } +@UnstableKMathAPI public fun Ring.pow(base: T, exponent: UInt): T = pow(base, exponent.toULong()) private fun Ring.powWithoutOptimization(base: T, exponent: ULong): T = when (exponent) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 45161149c..0dcbbe567 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -98,7 +98,10 @@ public class BigInt internal constructor( else -> BigInt(sign, multiplyMagnitudeByUInt(magnitude, other)) } + @UnstableKMathAPI public fun pow(other: ULong): BigInt = BigIntField { pow(this@BigInt, other) } + + @UnstableKMathAPI public fun pow(other: UInt): BigInt = BigIntField { pow(this@BigInt, other) } public operator fun times(other: Int): BigInt = when { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt index 8e3e6c777..7045c874e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt @@ -147,7 +147,7 @@ public interface PowerOperations : Algebra { } /** - * Raises this element to the power [pow]. + * Raises this element to the power [power]. * * @receiver the base. * @param power the exponent. diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt index abc88934c..d3fca4351 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.operations +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.testutils.RingVerifier import kotlin.math.pow import kotlin.test.Test @@ -22,23 +23,22 @@ internal class BigIntAlgebraTest { assertEquals(res, 1_000_000.toBigInt()) } + @UnstableKMathAPI @Test fun testKBigIntegerRingPow() { - BigIntField { - for (num in -5..5) - for (exponent in 0U..10U) { - assertEquals( - num.toDouble().pow(exponent.toInt()).toLong().toBigInt(), - num.toBigInt().pow(exponent.toULong()), - "$num ^ $exponent" - ) - assertEquals( - num.toDouble().pow(exponent.toInt()).toLong().toBigInt(), - num.toBigInt().pow(exponent), - "$num ^ $exponent" - ) - } - } + for (num in -5..5) + for (exponent in 0U..10U) { + assertEquals( + num.toDouble().pow(exponent.toInt()).toLong().toBigInt(), + num.toBigInt().pow(exponent.toULong()), + "$num ^ $exponent" + ) + assertEquals( + num.toDouble().pow(exponent.toInt()).toLong().toBigInt(), + num.toBigInt().pow(exponent), + "$num ^ $exponent" + ) + } } @Test From fcb960533823090eff6fae936ffa0058db65ff88 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 13 May 2021 22:59:35 +0700 Subject: [PATCH 334/393] Special rendering of Quaternion #330 --- .../space/kscience/kmath/complex/Complex.kt | 2 +- .../kscience/kmath/jupyter/KMathJupyter.kt | 24 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt index 8e28337f6..a96d046c9 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt @@ -187,7 +187,7 @@ public data class Complex(val re: Double, val im: Double) { public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble()) public constructor(re: Number) : this(re.toDouble(), 0.0) - public override fun toString(): String = "($re + i*$im)" + public override fun toString(): String = "($re + i * $im)" public companion object : MemorySpec { public override val objectSize: Int diff --git a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt index f3d553f2e..e3767e13c 100644 --- a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt +++ b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt @@ -12,18 +12,19 @@ import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer import space.kscience.kmath.ast.rendering.renderWithStringBuilder import space.kscience.kmath.complex.Complex +import space.kscience.kmath.complex.Quaternion import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.Structure2D -import space.kscience.kmath.operations.GroupOperations -import space.kscience.kmath.operations.RingOperations +import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asSequence /** * A function for conversion of number to MST for pretty print */ -public fun Number.toMst(): MST.Numeric = MST.Numeric(this) +public fun Number.toMst(): MST.Numeric = MST.Numeric(this) @JupyterLibrary internal class KMathJupyter : JupyterIntegration() { @@ -121,11 +122,18 @@ internal class KMathJupyter : JupyterIntegration() { } render { - MST.Binary( - operation = GroupOperations.PLUS_OPERATION, - left = MST.Numeric(it.re), - right = MST.Binary(RingOperations.TIMES_OPERATION, MST.Numeric(it.im), MST.Symbolic("i")), - ).toDisplayResult() + MstRing { + number(it.re) + number(it.im) * bindSymbol("i") + }.toDisplayResult() + } + + render { + MstRing { + number(it.w) + + number(it.x) * bindSymbol("i") + + number(it.x) * bindSymbol("j") + + number(it.x) * bindSymbol("k") + }.toDisplayResult() } } } From e110253d8f38171b91d4417c115713585e9faa29 Mon Sep 17 00:00:00 2001 From: Roland Grinis Date: Thu, 13 May 2021 19:26:18 +0100 Subject: [PATCH 335/393] remove cov from tensors API --- .../kmath/tensors/api/AnalyticTensorAlgebra.kt | 10 ---------- .../kscience/kmath/tensors/core/DoubleTensorAlgebra.kt | 10 +++++++++- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 1db986e77..e58af14db 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -67,16 +67,6 @@ public interface AnalyticTensorAlgebra : TensorPartialDivisionAlgebra { */ public fun Tensor.variance(dim: Int, keepDim: Boolean): Tensor - /** - * Returns the covariance matrix M of given vectors. - * - * M[i, j] contains covariance of i-th and j-th given vectors - * - * @param tensors the [List] of 1-dimensional tensors with same shape - * @return the covariance matrix - */ - public fun cov(tensors: List>): Tensor - //For information: https://pytorch.org/docs/stable/generated/torch.exp.html public fun Tensor.exp(): Tensor diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index c1694644f..78989f1f3 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -629,7 +629,15 @@ public open class DoubleTensorAlgebra : return ((x - x.mean()) * (y - y.mean())).mean() * n / (n - 1) } - override fun cov(tensors: List>): DoubleTensor { + /** + * Returns the covariance matrix M of given vectors. + * + * M[i, j] contains covariance of i-th and j-th given vectors + * + * @param tensors the [List] of 1-dimensional tensors with same shape + * @return the covariance matrix + */ + public fun cov(tensors: List>): DoubleTensor { check(tensors.isNotEmpty()) { "List must have at least 1 element" } val n = tensors.size val m = tensors[0].shape[0] From c2047474016f8c7de92b83f741c7bb00630cc1a9 Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Thu, 13 May 2021 22:44:33 +0300 Subject: [PATCH 336/393] Reusing of existing power function --- .../kmath/benchmarks/BigIntBenchmark.kt | 4 +- .../kscience/kmath/operations/Algebra.kt | 20 ---------- .../space/kscience/kmath/operations/BigInt.kt | 6 +-- .../kmath/operations/algebraExtensions.kt | 39 ++++++++++++------- .../kmath/operations/BigIntAlgebraTest.kt | 8 +--- .../kmath/operations/DoubleFieldTest.kt | 12 ++++++ 6 files changed, 41 insertions(+), 48 deletions(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index 21b097609..749cd5e75 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -21,7 +21,7 @@ internal class BigIntBenchmark { val kmNumber = BigIntField.number(Int.MAX_VALUE) val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE) - val largeKmNumber = BigIntField { number(11).pow(100_000UL) } + val largeKmNumber = BigIntField { number(11).pow(100_000U) } val largeJvmNumber: BigInteger = JBigIntegerField { number(11).pow(100_000) } val bigExponent = 50_000 @@ -67,7 +67,7 @@ internal class BigIntBenchmark { @Benchmark fun kmPower(blackhole: Blackhole) = BigIntField { - blackhole.consume(kmNumber.pow(bigExponent.toULong())) + blackhole.consume(kmNumber.pow(bigExponent.toUInt())) } @Benchmark diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 8881ae93c..b444ed964 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -253,26 +253,6 @@ public interface Ring : Group, RingOperations { public val one: T } -@UnstableKMathAPI -public fun Ring.pow(base: T, exponent: ULong): T = when { - this == zero && exponent > 0UL -> zero - this == one -> base - this == -one -> powWithoutOptimization(base, exponent % 2UL) - else -> powWithoutOptimization(base, exponent) -} - -@UnstableKMathAPI -public fun Ring.pow(base: T, exponent: UInt): T = pow(base, exponent.toULong()) - -private fun Ring.powWithoutOptimization(base: T, exponent: ULong): T = when (exponent) { - 0UL -> one - 1UL -> base - else -> { - val pre = powWithoutOptimization(base, exponent shr 1).let { it * it } - if (exponent and 1UL == 0UL) pre else pre * base - } -} - /** * Represents field without without multiplicative and additive identities, i.e. algebraic structure with associative, binary, commutative operations * [add] and [multiply]; binary operation [divide] as multiplication of left operand by reciprocal of right one. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 0dcbbe567..924ef07f4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -98,11 +98,7 @@ public class BigInt internal constructor( else -> BigInt(sign, multiplyMagnitudeByUInt(magnitude, other)) } - @UnstableKMathAPI - public fun pow(other: ULong): BigInt = BigIntField { pow(this@BigInt, other) } - - @UnstableKMathAPI - public fun pow(other: UInt): BigInt = BigIntField { pow(this@BigInt, other) } + public fun pow(exponent: UInt): BigInt = BigIntField.power(this@BigInt, exponent) public operator fun times(other: Int): BigInt = when { other > 0 -> this * kotlin.math.abs(other).toUInt() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index b8670553d..9691c9d17 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -97,34 +97,45 @@ public fun Sequence.averageWith(space: S): T where S : Ring, S : Sc //TODO optimized power operation /** - * Raises [arg] to the natural power [power]. + * Raises [arg] to the non-negative integer power [power]. + * + * Special case: 0 ^ 0 is 1. * * @receiver the algebra to provide multiplication. * @param arg the base. * @param power the exponent. * @return the base raised to the power. + * @author Evgeniy Zhelenskiy */ -public fun Ring.power(arg: T, power: Int): T { - require(power >= 0) { "The power can't be negative." } - require(power != 0 || arg != zero) { "The $zero raised to $power is not defined." } - if (power == 0) return one - var res = arg - repeat(power - 1) { res *= arg } - return res +public fun Ring.power(arg: T, power: UInt): T = when { + this == zero && power > 0U -> zero + this == one -> arg + this == -one -> powWithoutOptimization(arg, power % 2U) + else -> powWithoutOptimization(arg, power) } +private fun Ring.powWithoutOptimization(base: T, exponent: UInt): T = when (exponent) { + 0U -> one + 1U -> base + else -> { + val pre = powWithoutOptimization(base, exponent shr 1).let { it * it } + if (exponent and 1U == 0U) pre else pre * base + } +} + + /** * Raises [arg] to the integer power [power]. * + * Special case: 0 ^ 0 is 1. + * * @receiver the algebra to provide multiplication and division. * @param arg the base. * @param power the exponent. * @return the base raised to the power. - * @author Iaroslav Postovalov + * @author Iaroslav Postovalov, Evgeniy Zhelenskiy */ -public fun Field.power(arg: T, power: Int): T { - require(power != 0 || arg != zero) { "The $zero raised to $power is not defined." } - if (power == 0) return one - if (power < 0) return one / (this as Ring).power(arg, -power) - return (this as Ring).power(arg, power) +public fun Field.power(arg: T, power: Int): T = when { + power < 0 -> one / (this as Ring).power(arg, if (power == Int.MIN_VALUE) Int.MAX_VALUE.toUInt().inc() else (-power).toUInt()) + else -> (this as Ring).power(arg, power.toUInt()) } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt index d3fca4351..0527f5252 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt @@ -27,18 +27,12 @@ internal class BigIntAlgebraTest { @Test fun testKBigIntegerRingPow() { for (num in -5..5) - for (exponent in 0U..10U) { - assertEquals( - num.toDouble().pow(exponent.toInt()).toLong().toBigInt(), - num.toBigInt().pow(exponent.toULong()), - "$num ^ $exponent" - ) + for (exponent in 0U..10U) assertEquals( num.toDouble().pow(exponent.toInt()).toLong().toBigInt(), num.toBigInt().pow(exponent), "$num ^ $exponent" ) - } } @Test diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt index c482dc978..7e689d079 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt @@ -18,4 +18,16 @@ internal class DoubleFieldTest { val sqrt = DoubleField { sqrt(25 * one) } assertEquals(5.0, sqrt) } + + @Test + fun testPow() = DoubleField { + val num = 5 * one + assertEquals(5.0, power(num, 1)) + assertEquals(25.0, power(num, 2)) + assertEquals(1.0, power(num, 0)) + assertEquals(0.2, power(num, -1)) + assertEquals(0.04, power(num, -2)) + assertEquals(0.0, power(num, Int.MIN_VALUE)) + assertEquals(1.0, power(zero, 0)) + } } From bdb9ce6a59bf34b4ff21945f42a05c070752fcf7 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 14 May 2021 09:10:05 +0300 Subject: [PATCH 337/393] fixes to power --- .../kscience/kmath/operations/algebraExtensions.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 9691c9d17..338dc6a5c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -108,9 +108,9 @@ public fun Sequence.averageWith(space: S): T where S : Ring, S : Sc * @author Evgeniy Zhelenskiy */ public fun Ring.power(arg: T, power: UInt): T = when { - this == zero && power > 0U -> zero - this == one -> arg - this == -one -> powWithoutOptimization(arg, power % 2U) + arg == zero && power > 0U -> zero + arg == one -> arg + arg == -one -> powWithoutOptimization(arg, power % 2U) else -> powWithoutOptimization(arg, power) } @@ -135,7 +135,7 @@ private fun Ring.powWithoutOptimization(base: T, exponent: UInt): T = whe * @return the base raised to the power. * @author Iaroslav Postovalov, Evgeniy Zhelenskiy */ -public fun Field.power(arg: T, power: Int): T = when { - power < 0 -> one / (this as Ring).power(arg, if (power == Int.MIN_VALUE) Int.MAX_VALUE.toUInt().inc() else (-power).toUInt()) - else -> (this as Ring).power(arg, power.toUInt()) +public fun Field.power(arg: T, power: UInt): T = when { + power < 0 -> one / (this as Ring).power(arg, power) + else -> (this as Ring).power(arg, power) } From 1b60f71ed0efbba385c3e8b65ab4147deff013db Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 14 May 2021 09:14:48 +0300 Subject: [PATCH 338/393] Revert "fixes to power" This reverts commit bdb9ce6a --- .../kscience/kmath/operations/algebraExtensions.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 338dc6a5c..9691c9d17 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -108,9 +108,9 @@ public fun Sequence.averageWith(space: S): T where S : Ring, S : Sc * @author Evgeniy Zhelenskiy */ public fun Ring.power(arg: T, power: UInt): T = when { - arg == zero && power > 0U -> zero - arg == one -> arg - arg == -one -> powWithoutOptimization(arg, power % 2U) + this == zero && power > 0U -> zero + this == one -> arg + this == -one -> powWithoutOptimization(arg, power % 2U) else -> powWithoutOptimization(arg, power) } @@ -135,7 +135,7 @@ private fun Ring.powWithoutOptimization(base: T, exponent: UInt): T = whe * @return the base raised to the power. * @author Iaroslav Postovalov, Evgeniy Zhelenskiy */ -public fun Field.power(arg: T, power: UInt): T = when { - power < 0 -> one / (this as Ring).power(arg, power) - else -> (this as Ring).power(arg, power) +public fun Field.power(arg: T, power: Int): T = when { + power < 0 -> one / (this as Ring).power(arg, if (power == Int.MIN_VALUE) Int.MAX_VALUE.toUInt().inc() else (-power).toUInt()) + else -> (this as Ring).power(arg, power.toUInt()) } From 1a615c503d4fd337474d761485ecdc285d681c83 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 14 May 2021 09:20:49 +0300 Subject: [PATCH 339/393] re-apply bigint fix --- .../space/kscience/kmath/operations/algebraExtensions.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 9691c9d17..830c504f3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -108,9 +108,9 @@ public fun Sequence.averageWith(space: S): T where S : Ring, S : Sc * @author Evgeniy Zhelenskiy */ public fun Ring.power(arg: T, power: UInt): T = when { - this == zero && power > 0U -> zero - this == one -> arg - this == -one -> powWithoutOptimization(arg, power % 2U) + arg == zero && power > 0U -> zero + arg == one -> arg + arg == -one -> powWithoutOptimization(arg, power % 2U) else -> powWithoutOptimization(arg, power) } From dc9ec54644c4d7b9675bfd9959ee2e1f84829152 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 14 May 2021 09:32:24 +0300 Subject: [PATCH 340/393] naming fix and doc update --- CHANGELOG.md | 1 + kmath-core/api/kmath-core.api | 3 ++- .../space/kscience/kmath/operations/BigInt.kt | 2 +- .../kmath/operations/algebraExtensions.kt | 22 +++++++++---------- .../kmath/operations/BigIntOperationsTest.kt | 14 +++++++----- .../kmath/operations/DoubleFieldTest.kt | 14 ++++++------ 6 files changed, 30 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 286be25e5..732cc87a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Extended operations for ND4J fields - Jupyter Notebook integration module (kmath-jupyter) - `@PerformancePitfall` annotation to mark possibly slow API +- BigInt operation performance improvement and fixes by @zhelenskiy (#328) ### Changed - Exponential operations merged with hyperbolic functions diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 14bc70a2a..7b09b668b 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -1020,7 +1020,7 @@ public final class space/kscience/kmath/operations/AlgebraExtensionsKt { public static final fun averageWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Ring;)Ljava/lang/Object; public static final fun averageWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Ring;)Ljava/lang/Object; public static final fun power (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;I)Ljava/lang/Object; - public static final fun power (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;I)Ljava/lang/Object; + public static final fun power-jXDDuk8 (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;I)Ljava/lang/Object; public static final fun sum (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Iterable;)Ljava/lang/Object; public static final fun sum (Lspace/kscience/kmath/operations/Ring;Lkotlin/sequences/Sequence;)Ljava/lang/Object; public static final fun sumWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Ring;)Ljava/lang/Object; @@ -1050,6 +1050,7 @@ public final class space/kscience/kmath/operations/BigInt : java/lang/Comparable public final fun modPow (Lspace/kscience/kmath/operations/BigInt;Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; public final fun or (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; public final fun plus (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; + public final fun pow-WZ4Q5Ns (I)Lspace/kscience/kmath/operations/BigInt; public final fun rem (I)I public final fun rem (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; public final fun shl (I)Lspace/kscience/kmath/operations/BigInt; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 924ef07f4..ac53c4d5e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -98,7 +98,7 @@ public class BigInt internal constructor( else -> BigInt(sign, multiplyMagnitudeByUInt(magnitude, other)) } - public fun pow(exponent: UInt): BigInt = BigIntField.power(this@BigInt, exponent) + public fun pow(exponent: UInt): BigInt = BigIntField.power(this, exponent) public operator fun times(other: Int): BigInt = when { other > 0 -> this * kotlin.math.abs(other).toUInt() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 830c504f3..422b1ae1a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -97,21 +97,21 @@ public fun Sequence.averageWith(space: S): T where S : Ring, S : Sc //TODO optimized power operation /** - * Raises [arg] to the non-negative integer power [power]. + * Raises [arg] to the non-negative integer power [exponent]. * * Special case: 0 ^ 0 is 1. * * @receiver the algebra to provide multiplication. * @param arg the base. - * @param power the exponent. + * @param exponent the exponent. * @return the base raised to the power. * @author Evgeniy Zhelenskiy */ -public fun Ring.power(arg: T, power: UInt): T = when { - arg == zero && power > 0U -> zero +public fun Ring.power(arg: T, exponent: UInt): T = when { + arg == zero && exponent > 0U -> zero arg == one -> arg - arg == -one -> powWithoutOptimization(arg, power % 2U) - else -> powWithoutOptimization(arg, power) + arg == -one -> powWithoutOptimization(arg, exponent % 2U) + else -> powWithoutOptimization(arg, exponent) } private fun Ring.powWithoutOptimization(base: T, exponent: UInt): T = when (exponent) { @@ -125,17 +125,17 @@ private fun Ring.powWithoutOptimization(base: T, exponent: UInt): T = whe /** - * Raises [arg] to the integer power [power]. + * Raises [arg] to the integer power [exponent]. * * Special case: 0 ^ 0 is 1. * * @receiver the algebra to provide multiplication and division. * @param arg the base. - * @param power the exponent. + * @param exponent the exponent. * @return the base raised to the power. * @author Iaroslav Postovalov, Evgeniy Zhelenskiy */ -public fun Field.power(arg: T, power: Int): T = when { - power < 0 -> one / (this as Ring).power(arg, if (power == Int.MIN_VALUE) Int.MAX_VALUE.toUInt().inc() else (-power).toUInt()) - else -> (this as Ring).power(arg, power.toUInt()) +public fun Field.power(arg: T, exponent: Int): T = when { + exponent < 0 -> one / (this as Ring).power(arg, if (exponent == Int.MIN_VALUE) Int.MAX_VALUE.toUInt().inc() else (-exponent).toUInt()) + else -> (this as Ring).power(arg, exponent.toUInt()) } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt index 9f35f7a69..26d6af224 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt @@ -7,7 +7,10 @@ package space.kscience.kmath.operations import kotlin.random.Random import kotlin.random.nextUInt -import kotlin.test.* +import kotlin.test.Test +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals +import kotlin.test.assertFalse @kotlin.ExperimentalUnsignedTypes class BigIntOperationsTest { @@ -153,14 +156,13 @@ class BigIntOperationsTest { @Test fun testKaratsuba() { + val random = Random(2222) val x = uintArrayOf(12U, 345U) val y = uintArrayOf(6U, 789U) assertContentEquals(BigInt.naiveMultiplyMagnitudes(x, y), BigInt.karatsubaMultiplyMagnitudes(x, y)) - repeat(1000) { - val x1 = UIntArray(Random.nextInt(100, 1000)) { Random.nextUInt() } - val y1 = UIntArray(Random.nextInt(100, 1000)) { Random.nextUInt() } - assertContentEquals(BigInt.naiveMultiplyMagnitudes(x1, y1), BigInt.karatsubaMultiplyMagnitudes(x1, y1)) - } + val x1 = UIntArray(Random.nextInt(100, 1000)) { random.nextUInt() } + val y1 = UIntArray(Random.nextInt(100, 1000)) { random.nextUInt() } + assertContentEquals(BigInt.naiveMultiplyMagnitudes(x1, y1), BigInt.karatsubaMultiplyMagnitudes(x1, y1)) } @Test diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt index 7e689d079..76171fedd 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt @@ -22,12 +22,12 @@ internal class DoubleFieldTest { @Test fun testPow() = DoubleField { val num = 5 * one - assertEquals(5.0, power(num, 1)) - assertEquals(25.0, power(num, 2)) - assertEquals(1.0, power(num, 0)) - assertEquals(0.2, power(num, -1)) - assertEquals(0.04, power(num, -2)) - assertEquals(0.0, power(num, Int.MIN_VALUE)) - assertEquals(1.0, power(zero, 0)) + assertEquals(5.0, power(num, 1), 0.01) + assertEquals(25.0, power(num, 2), 0.01) + assertEquals(1.0, power(num, 0), 0.01) + assertEquals(0.2, power(num, -1), 0.01) + assertEquals(0.04, power(num, -2), 0.01) + assertEquals(0.0, power(num, Int.MIN_VALUE), 0.01) + assertEquals(1.0, power(zero, 0), 0.01) } } From cf555bc8ae6a233b33567fb4f95acfcdcb0379bb Mon Sep 17 00:00:00 2001 From: zhelenskiy Date: Fri, 14 May 2021 10:48:57 +0300 Subject: [PATCH 341/393] TODO removed as I already added what neeed --- .../kotlin/space/kscience/kmath/operations/algebraExtensions.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 422b1ae1a..7967aeadb 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -94,8 +94,6 @@ public fun Iterable.averageWith(space: S): T where S : Ring, S : Sc public fun Sequence.averageWith(space: S): T where S : Ring, S : ScaleOperations = space.average(this) -//TODO optimized power operation - /** * Raises [arg] to the non-negative integer power [exponent]. * From 6eb95f26eb68082fcc47462089fdee33a25eeb55 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 14 May 2021 12:11:37 +0300 Subject: [PATCH 342/393] Additional piecewise extension --- .../kotlin/space/kscience/kmath/functions/Piecewise.kt | 9 +++++++++ .../kscience/kmath/interpolation/SplineInterpolator.kt | 8 +++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index 6d481e334..dae55502d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -79,4 +79,13 @@ public class OrderedPiecewisePolynomial>(delimiter: T) : public fun , C : Ring> PiecewisePolynomial.value(ring: C, arg: T): T? = findPiece(arg)?.value(ring, arg) +/** + * Convert this polynomial to a function returning nullable value (null if argument is outside piecewise range). + */ public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { value(ring, it) } + +/** + * Convert this polynomial to a function using [defaultValue] for arguments outside the piecewise range. + */ +public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C, defaultValue: T): (T) -> T = + { value(ring, it) ?: defaultValue } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index f00b66a4c..2d2ff6f26 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -42,9 +42,11 @@ public class SplineInterpolator>( val g = 2.0 * (points.x[i + 1] - points.x[i - 1]) - h[i - 1] * mu[i - 1] mu[i] = h[i] / g - z[i] = - (3.0 * (points.y[i + 1] * h[i - 1] - points.x[i] * (points.x[i + 1] - points.x[i - 1]) + points.y[i - 1] * h[i]) / (h[i - 1] * h[i]) - - h[i - 1] * z[i - 1]) / g + z[i] = (3.0 * (points.y[i + 1] * h[i - 1] + - points.x[i] * (points.x[i + 1] - points.x[i - 1]) + + points.y[i - 1] * h[i]) / (h[i - 1] * h[i]) + - h[i - 1] * z[i - 1] + ) / g } // cubic spline coefficients -- b is linear, c quadratic, d is cubic (original y's are constants) From fff737768764a4f1fecfe6ad165304be1e036e34 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 14 May 2021 12:42:27 +0300 Subject: [PATCH 343/393] ColumnarData returns nullable column --- CHANGELOG.md | 1 + .../kotlin/space/kscience/kmath/data/ColumnarData.kt | 2 +- .../kotlin/space/kscience/kmath/data/XYColumnarData.kt | 4 ++-- .../kotlin/space/kscience/kmath/data/XYZColumnarData.kt | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 732cc87a2..3a5bde44a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ - Separated benchmarks and examples - Rewritten EJML module without ejml-simple - Stability of kmath-ast and kmath-kotilngrad promoted to EXPERIMENTAL. +- ColumnarData returns nullable column ### Deprecated diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt index febf615a8..b1c7cacd3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt @@ -19,7 +19,7 @@ import space.kscience.kmath.structures.Buffer public interface ColumnarData { public val size: Int - public operator fun get(symbol: Symbol): Buffer + public operator fun get(symbol: Symbol): Buffer? } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt index 56bb59826..bbd679ce9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt @@ -27,10 +27,10 @@ public interface XYColumnarData : ColumnarData { */ public val y: Buffer - override fun get(symbol: Symbol): Buffer = when (symbol) { + override fun get(symbol: Symbol): Buffer? = when (symbol) { Symbol.x -> x Symbol.y -> y - else -> error("A column for symbol $symbol not found") + else -> null } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt index d76a44e9e..3972429a5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt @@ -17,10 +17,10 @@ import space.kscience.kmath.structures.Buffer public interface XYZColumnarData : XYColumnarData { public val z: Buffer - override fun get(symbol: Symbol): Buffer = when (symbol) { + override fun get(symbol: Symbol): Buffer? = when (symbol) { Symbol.x -> x Symbol.y -> y Symbol.z -> z - else -> error("A column for symbol $symbol not found") + else -> null } } \ No newline at end of file From 42d130f69c866f0d2456cf0698c83dab2e1f6bc7 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 14 May 2021 15:59:17 +0300 Subject: [PATCH 344/393] Build tools update. Cleanup --- build.gradle.kts | 2 +- .../kmath/tensors/DataSetNormalization.kt | 44 +++--- .../tensors/LinearSystemSolvingWithLUP.kt | 134 +++++++++--------- .../kscience/kmath/tensors/NeuralNetwork.kt | 112 +++++++-------- .../space/kscience/kmath/tensors/PCA.kt | 96 ++++++------- .../space/kscience/kmath/data/ColumnarData.kt | 3 + settings.gradle.kts | 2 +- 7 files changed, 191 insertions(+), 202 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 406a46810..e14d303fc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.0-dev-8" + version = "0.3.0-dev-9" } subprojects { diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt index 6fbf16a91..74795cc68 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/DataSetNormalization.kt @@ -11,36 +11,32 @@ import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra // Dataset normalization -fun main() { +fun main() = BroadcastDoubleTensorAlgebra { // work in context with broadcast methods + // take dataset of 5-element vectors from normal distribution + val dataset = randomNormal(intArrayOf(100, 5)) * 1.5 // all elements from N(0, 1.5) - // work in context with broadcast methods - BroadcastDoubleTensorAlgebra { - // take dataset of 5-element vectors from normal distribution - val dataset = randomNormal(intArrayOf(100, 5)) * 1.5 // all elements from N(0, 1.5) - - dataset += fromArray( - intArrayOf(5), - doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means - ) + dataset += fromArray( + intArrayOf(5), + doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means + ) - // find out mean and standard deviation of each column - val mean = dataset.mean(0, false) - val std = dataset.std(0, false) + // find out mean and standard deviation of each column + val mean = dataset.mean(0, false) + val std = dataset.std(0, false) - println("Mean:\n$mean") - println("Standard deviation:\n$std") + println("Mean:\n$mean") + println("Standard deviation:\n$std") - // also we can calculate other statistic as minimum and maximum of rows - println("Minimum:\n${dataset.min(0, false)}") - println("Maximum:\n${dataset.max(0, false)}") + // also we can calculate other statistic as minimum and maximum of rows + println("Minimum:\n${dataset.min(0, false)}") + println("Maximum:\n${dataset.max(0, false)}") - // now we can scale dataset with mean normalization - val datasetScaled = (dataset - mean) / std + // now we can scale dataset with mean normalization + val datasetScaled = (dataset - mean) / std - // find out mean and std of scaled dataset + // find out mean and std of scaled dataset - println("Mean of scaled:\n${datasetScaled.mean(0, false)}") - println("Mean of scaled:\n${datasetScaled.std(0, false)}") - } + println("Mean of scaled:\n${datasetScaled.mean(0, false)}") + println("Mean of scaled:\n${datasetScaled.std(0, false)}") } \ No newline at end of file diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt index 78370b517..6453ca44e 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/LinearSystemSolvingWithLUP.kt @@ -6,92 +6,88 @@ package space.kscience.kmath.tensors import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensor // solving linear system with LUP decomposition -fun main () { +fun main() = BroadcastDoubleTensorAlgebra {// work in context with linear operations - // work in context with linear operations - BroadcastDoubleTensorAlgebra { + // set true value of x + val trueX = fromArray( + intArrayOf(4), + doubleArrayOf(-2.0, 1.5, 6.8, -2.4) + ) - // set true value of x - val trueX = fromArray( - intArrayOf(4), - doubleArrayOf(-2.0, 1.5, 6.8, -2.4) + // and A matrix + val a = fromArray( + intArrayOf(4, 4), + doubleArrayOf( + 0.5, 10.5, 4.5, 1.0, + 8.5, 0.9, 12.8, 0.1, + 5.56, 9.19, 7.62, 5.45, + 1.0, 2.0, -3.0, -2.5 ) + ) - // and A matrix - val a = fromArray( - intArrayOf(4, 4), - doubleArrayOf( - 0.5, 10.5, 4.5, 1.0, - 8.5, 0.9, 12.8, 0.1, - 5.56, 9.19, 7.62, 5.45, - 1.0, 2.0, -3.0, -2.5 - ) - ) + // calculate y value + val b = a dot trueX - // calculate y value - val b = a dot trueX + // check out A and b + println("A:\n$a") + println("b:\n$b") - // check out A and b - println("A:\n$a") - println("b:\n$b") + // solve `Ax = b` system using LUP decomposition - // solve `Ax = b` system using LUP decomposition + // get P, L, U such that PA = LU + val (p, l, u) = a.lu() - // get P, L, U such that PA = LU - val (p, l, u) = a.lu() + // check that P is permutation matrix + println("P:\n$p") + // L is lower triangular matrix and U is upper triangular matrix + println("L:\n$l") + println("U:\n$u") + // and PA = LU + println("PA:\n${p dot a}") + println("LU:\n${l dot u}") - // check that P is permutation matrix - println("P:\n$p") - // L is lower triangular matrix and U is upper triangular matrix - println("L:\n$l") - println("U:\n$u") - // and PA = LU - println("PA:\n${p dot a}") - println("LU:\n${l dot u}") - - /* Ax = b; - PAx = Pb; - LUx = Pb; - let y = Ux, then - Ly = Pb -- this system can be easily solved, since the matrix L is lower triangular; - Ux = y can be solved the same way, since the matrix L is upper triangular - */ + /* Ax = b; + PAx = Pb; + LUx = Pb; + let y = Ux, then + Ly = Pb -- this system can be easily solved, since the matrix L is lower triangular; + Ux = y can be solved the same way, since the matrix L is upper triangular + */ - // this function returns solution x of a system lx = b, l should be lower triangular - fun solveLT(l: DoubleTensor, b: DoubleTensor): DoubleTensor { - val n = l.shape[0] - val x = zeros(intArrayOf(n)) - for (i in 0 until n){ - x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)] - } - return x - } - - val y = solveLT(l, p dot b) - - // solveLT(l, b) function can be easily adapted for upper triangular matrix by the permutation matrix revMat - // create it by placing ones on side diagonal - val revMat = u.zeroesLike() - val n = revMat.shape[0] + // this function returns solution x of a system lx = b, l should be lower triangular + fun solveLT(l: DoubleTensor, b: DoubleTensor): DoubleTensor { + val n = l.shape[0] + val x = zeros(intArrayOf(n)) for (i in 0 until n) { - revMat[intArrayOf(i, n - 1 - i)] = 1.0 + x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)] } - - // solution of system ux = b, u should be upper triangular - fun solveUT(u: DoubleTensor, b: DoubleTensor): DoubleTensor = revMat dot solveLT( - revMat dot u dot revMat, revMat dot b - ) - - val x = solveUT(u, y) - - println("True x:\n$trueX") - println("x founded with LU method:\n$x") + return x } + + val y = solveLT(l, p dot b) + + // solveLT(l, b) function can be easily adapted for upper triangular matrix by the permutation matrix revMat + // create it by placing ones on side diagonal + val revMat = u.zeroesLike() + val n = revMat.shape[0] + for (i in 0 until n) { + revMat[intArrayOf(i, n - 1 - i)] = 1.0 + } + + // solution of system ux = b, u should be upper triangular + fun solveUT(u: DoubleTensor, b: DoubleTensor): DoubleTensor = revMat dot solveLT( + revMat dot u dot revMat, revMat dot b + ) + + val x = solveUT(u, y) + + println("True x:\n$trueX") + println("x founded with LU method:\n$x") } \ No newline at end of file diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt index 5b3c2e1cd..b262bee02 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/NeuralNetwork.kt @@ -25,7 +25,7 @@ interface Layer { // activation layer open class Activation( val activation: (DoubleTensor) -> DoubleTensor, - val activationDer: (DoubleTensor) -> DoubleTensor + val activationDer: (DoubleTensor) -> DoubleTensor, ) : Layer { override fun forward(input: DoubleTensor): DoubleTensor { return activation(input) @@ -62,7 +62,7 @@ class Sigmoid : Activation(::sigmoid, ::sigmoidDer) class Dense( private val inputUnits: Int, private val outputUnits: Int, - private val learningRate: Double = 0.1 + private val learningRate: Double = 0.1, ) : Layer { private val weights: DoubleTensor = DoubleTensorAlgebra { @@ -74,8 +74,8 @@ class Dense( private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(intArrayOf(outputUnits)) } - override fun forward(input: DoubleTensor): DoubleTensor { - return BroadcastDoubleTensorAlgebra { (input dot weights) + bias } + override fun forward(input: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra { + (input dot weights) + bias } override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { @@ -116,7 +116,7 @@ class NeuralNetwork(private val layers: List) { onesForAnswers[intArrayOf(index, label)] = 1.0 } - val softmaxValue = yPred.exp() / yPred.exp().sum(dim = 1, keepDim = true) + val softmaxValue = yPred.exp() / yPred.exp().sum(dim = 1, keepDim = true) (-onesForAnswers + softmaxValue) / (yPred.shape[0].toDouble()) } @@ -175,67 +175,65 @@ class NeuralNetwork(private val layers: List) { @OptIn(ExperimentalStdlibApi::class) -fun main() { - BroadcastDoubleTensorAlgebra { - val features = 5 - val sampleSize = 250 - val trainSize = 180 - //val testSize = sampleSize - trainSize +fun main() = BroadcastDoubleTensorAlgebra { + val features = 5 + val sampleSize = 250 + val trainSize = 180 + //val testSize = sampleSize - trainSize - // take sample of features from normal distribution - val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5 + // take sample of features from normal distribution + val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5 - x += fromArray( - intArrayOf(5), - doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means - ) + x += fromArray( + intArrayOf(5), + doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means + ) - // define class like '1' if the sum of features > 0 and '0' otherwise - val y = fromArray( - intArrayOf(sampleSize, 1), - DoubleArray(sampleSize) { i -> - if (x[i].sum() > 0.0) { - 1.0 - } else { - 0.0 - } + // define class like '1' if the sum of features > 0 and '0' otherwise + val y = fromArray( + intArrayOf(sampleSize, 1), + DoubleArray(sampleSize) { i -> + if (x[i].sum() > 0.0) { + 1.0 + } else { + 0.0 } - ) - - // split train ans test - val trainIndices = (0 until trainSize).toList().toIntArray() - val testIndices = (trainSize until sampleSize).toList().toIntArray() - - val xTrain = x.rowsByIndices(trainIndices) - val yTrain = y.rowsByIndices(trainIndices) - - val xTest = x.rowsByIndices(testIndices) - val yTest = y.rowsByIndices(testIndices) - - // build model - val layers = buildList { - add(Dense(features, 64)) - add(ReLU()) - add(Dense(64, 16)) - add(ReLU()) - add(Dense(16, 2)) - add(Sigmoid()) } - val model = NeuralNetwork(layers) + ) - // fit it with train data - model.fit(xTrain, yTrain, batchSize = 20, epochs = 10) + // split train ans test + val trainIndices = (0 until trainSize).toList().toIntArray() + val testIndices = (trainSize until sampleSize).toList().toIntArray() - // make prediction - val prediction = model.predict(xTest) + val xTrain = x.rowsByIndices(trainIndices) + val yTrain = y.rowsByIndices(trainIndices) - // process raw prediction via argMax - val predictionLabels = prediction.argMax(1, true) - - // find out accuracy - val acc = accuracy(yTest, predictionLabels) - println("Test accuracy:$acc") + val xTest = x.rowsByIndices(testIndices) + val yTest = y.rowsByIndices(testIndices) + // build model + val layers = buildList { + add(Dense(features, 64)) + add(ReLU()) + add(Dense(64, 16)) + add(ReLU()) + add(Dense(16, 2)) + add(Sigmoid()) } + val model = NeuralNetwork(layers) + + // fit it with train data + model.fit(xTrain, yTrain, batchSize = 20, epochs = 10) + + // make prediction + val prediction = model.predict(xTest) + + // process raw prediction via argMax + val predictionLabels = prediction.argMax(1, true) + + // find out accuracy + val acc = accuracy(yTest, predictionLabels) + println("Test accuracy:$acc") + } diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt index f8ac13d3f..e47b87177 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -11,68 +11,64 @@ import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra // simple PCA -fun main(){ +fun main() = BroadcastDoubleTensorAlgebra { // work in context with broadcast methods val seed = 100500L - // work in context with broadcast methods - BroadcastDoubleTensorAlgebra { + // assume x is range from 0 until 10 + val x = fromArray( + intArrayOf(10), + (0 until 10).toList().map { it.toDouble() }.toDoubleArray() + ) - // assume x is range from 0 until 10 - val x = fromArray( - intArrayOf(10), - (0 until 10).toList().map { it.toDouble() }.toDoubleArray() - ) + // take y dependent on x with noise + val y = 2.0 * x + (3.0 + x.randomNormalLike(seed) * 1.5) - // take y dependent on x with noise - val y = 2.0 * x + (3.0 + x.randomNormalLike(seed) * 1.5) + println("x:\n$x") + println("y:\n$y") - println("x:\n$x") - println("y:\n$y") + // stack them into single dataset + val dataset = stack(listOf(x, y)).transpose() - // stack them into single dataset - val dataset = stack(listOf(x, y)).transpose() + // normalize both x and y + val xMean = x.mean() + val yMean = y.mean() - // normalize both x and y - val xMean = x.mean() - val yMean = y.mean() + val xStd = x.std() + val yStd = y.std() - val xStd = x.std() - val yStd = y.std() + val xScaled = (x - xMean) / xStd + val yScaled = (y - yMean) / yStd - val xScaled = (x - xMean) / xStd - val yScaled = (y - yMean) / yStd + // save means ans standard deviations for further recovery + val mean = fromArray( + intArrayOf(2), + doubleArrayOf(xMean, yMean) + ) + println("Means:\n$mean") - // save means ans standard deviations for further recovery - val mean = fromArray( - intArrayOf(2), - doubleArrayOf(xMean, yMean) - ) - println("Means:\n$mean") + val std = fromArray( + intArrayOf(2), + doubleArrayOf(xStd, yStd) + ) + println("Standard deviations:\n$std") - val std = fromArray( - intArrayOf(2), - doubleArrayOf(xStd, yStd) - ) - println("Standard deviations:\n$std") + // calculate the covariance matrix of scaled x and y + val covMatrix = cov(listOf(xScaled, yScaled)) + println("Covariance matrix:\n$covMatrix") - // calculate the covariance matrix of scaled x and y - val covMatrix = cov(listOf(xScaled, yScaled)) - println("Covariance matrix:\n$covMatrix") + // and find out eigenvector of it + val (_, evecs) = covMatrix.symEig() + val v = evecs[0] + println("Eigenvector:\n$v") - // and find out eigenvector of it - val (_, evecs) = covMatrix.symEig() - val v = evecs[0] - println("Eigenvector:\n$v") + // reduce dimension of dataset + val datasetReduced = v dot stack(listOf(xScaled, yScaled)) + println("Reduced data:\n$datasetReduced") - // reduce dimension of dataset - val datasetReduced = v dot stack(listOf(xScaled, yScaled)) - println("Reduced data:\n$datasetReduced") - - // we can restore original data from reduced data. - // for example, find 7th element of dataset - val n = 7 - val restored = (datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean - println("Original value:\n${dataset[n]}") - println("Restored value:\n$restored") - } + // we can restore original data from reduced data. + // for example, find 7th element of dataset + val n = 7 + val restored = (datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean + println("Original value:\n${dataset[n]}") + println("Restored value:\n$restored") } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt index b1c7cacd3..f5193ecd2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt @@ -19,6 +19,9 @@ import space.kscience.kmath.structures.Buffer public interface ColumnarData { public val size: Int + /** + * Provide a column by symbol or null if column with given symbol is not defined + */ public operator fun get(symbol: Symbol): Buffer? } diff --git a/settings.gradle.kts b/settings.gradle.kts index 27e74c902..7ebfe1f59 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,7 +5,7 @@ pluginManagement { maven("https://repo.kotlin.link") } - val toolsVersion = "0.9.6" + val toolsVersion = "0.9.7" val kotlinVersion = "1.5.0" plugins { From b94172fd2208c6b27447dc8265116a3f1b31ee82 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 14 May 2021 21:15:24 +0700 Subject: [PATCH 345/393] Link to Kotlingrad documentation --- build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle.kts b/build.gradle.kts index 406a46810..1b9eb2801 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,6 +32,7 @@ subprojects { externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/") externalDocumentationLink("https://deeplearning4j.org/api/latest/") externalDocumentationLink("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/") + externalDocumentationLink("https://breandan.net/kotlingrad/kotlingrad/kotlingrad/") } } } From b33c68e315c086d91446bec4f7554cd32d6b82ca Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 14 May 2021 21:47:21 +0700 Subject: [PATCH 346/393] Link to Kotlingrad documentation --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 1b9eb2801..63fddae3d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -27,12 +27,12 @@ subprojects { dokkaSourceSets.all { val readmeFile = File(this@subprojects.projectDir, "README.md") - if (readmeFile.exists()) includes.setFrom(includes + readmeFile.absolutePath) + if (readmeFile.exists()) includes.from(readmeFile.absolutePath) externalDocumentationLink("http://ejml.org/javadoc/") externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/") externalDocumentationLink("https://deeplearning4j.org/api/latest/") externalDocumentationLink("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/") - externalDocumentationLink("https://breandan.net/kotlingrad/kotlingrad/kotlingrad/") + externalDocumentationLink("https://breandan.net/kotlingrad/kotlingrad/", "https://breandan.net/kotlingrad/kotlingrad/kotlingrad/package-list") } } } From 6f39b38a7203d7b40d794d1682c1cf18d546defc Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 16 May 2021 13:59:37 +0300 Subject: [PATCH 347/393] Refactor integrator API. --- .../kscience/kmath/functions/integrate.kt | 4 +-- .../kmath/functions/matrixIntegration.kt | 4 +-- .../integration/GaussRuleIntegrator.kt | 2 +- .../kmath/integration/GaussIntegrator.kt | 20 +++++-------- .../kmath/integration/UnivariateIntegrand.kt | 28 +++++++++++-------- .../kmath/integration/GaussIntegralTest.kt | 4 +-- 6 files changed, 28 insertions(+), 34 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt index 6990e8c8f..73770726b 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt @@ -5,8 +5,6 @@ package space.kscience.kmath.functions -import space.kscience.kmath.integration.integrate -import space.kscience.kmath.integration.value import space.kscience.kmath.operations.DoubleField import kotlin.math.pow @@ -18,5 +16,5 @@ fun main() { val result = DoubleField.integrate(0.0..10.0, function = function) //the value is nullable because in some cases the integration could not succeed - println(result.value) + println(result.valueOrNull) } \ No newline at end of file diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt index 8020df8f6..184672044 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt @@ -5,8 +5,6 @@ package space.kscience.kmath.functions -import space.kscience.kmath.integration.integrate -import space.kscience.kmath.integration.value import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.nd import space.kscience.kmath.operations.DoubleField @@ -27,6 +25,6 @@ fun main(): Unit = DoubleField { val result = integrate(0.0..10.0, function = function) //the value is nullable because in some cases the integration could not succeed - println(result.value) + println(result.valueOrNull) } } \ No newline at end of file diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt index 1c9915563..304fdec8f 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt @@ -78,6 +78,6 @@ public class GaussRuleIntegrator( function: (Double) -> Double, ): Double = GaussRuleIntegrator(numPoints, type).integrate( UnivariateIntegrand(function, IntegrationRange(range)) - ).value!! + ).valueOrNull!! } } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index ae82a40be..d6e716371 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -66,31 +66,25 @@ public class GaussIntegrator( return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + points.size) } - public companion object { - - } + public companion object } /** - * Integrate [T]-valued univariate function using provided set of [IntegrandFeature] - * Following features are evaluated: + * Create a Gauss-Legendre integrator for this field + * Following integrand features are accepted: * * [GaussIntegratorRuleFactory] - A factory for computing the Gauss integration rule. By default uses [GaussLegendreRuleFactory] * * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. * * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 10 points. * * [UnivariateIntegrandRanges] - Set of ranges and number of points per range. Defaults to given [IntegrationRange] and [IntegrandMaxCalls] */ -@UnstableKMathAPI -public fun Field.integrate( - vararg features: IntegrandFeature, - function: (Double) -> T, -): UnivariateIntegrand = GaussIntegrator(this).integrate(UnivariateIntegrand(function, *features)) +public val Field.integrator: GaussIntegrator get() = GaussIntegrator(this) /** - * Use [GaussIntegrator.Companion.integrate] to integrate the function in the current algebra with given [range] and [numPoints] + * Use [integrate] to integrate the function in the current algebra with given [range] and [numPoints] */ @UnstableKMathAPI -public fun Field.integrate( +public fun GaussIntegrator.integrate( range: ClosedRange, order: Int = 10, intervals: Int = 10, @@ -104,7 +98,7 @@ public fun Field.integrate( val ranges = UnivariateIntegrandRanges( (0 until intervals).map { i -> (rangeSize * i)..(rangeSize * (i + 1)) to order } ) - return GaussIntegrator(this).integrate( + return integrate( UnivariateIntegrand( function, IntegrationRange(range), diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index 51ea57a33..3cafc9782 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -35,37 +35,41 @@ public typealias UnivariateIntegrator = Integrator> @JvmInline public value class IntegrationRange(public val range: ClosedRange) : IntegrandFeature -public val UnivariateIntegrand.value: T? get() = getFeature>()?.value +/** + * Value of the integrand if it is present or null + */ +public val UnivariateIntegrand.valueOrNull: T? get() = getFeature>()?.value + +/** + * Value of the integrand or error + */ +public val UnivariateIntegrand.value: T get() = valueOrNull ?: error("No value in the integrand") /** * A shortcut method to integrate a [function] in [range] with additional [features]. * The [function] is placed in the end position to allow passing a lambda. */ @UnstableKMathAPI -public fun UnivariateIntegrator.integrate( +public fun UnivariateIntegrator.integrate( range: ClosedRange, vararg features: IntegrandFeature, - function: (Double) -> Double, -): Double = integrate( - UnivariateIntegrand(function, IntegrationRange(range), *features) -).value ?: error("Unexpected: no value after integration.") + function: (Double) -> T, +): UnivariateIntegrand = integrate(UnivariateIntegrand(function, IntegrationRange(range), *features)) /** * A shortcut method to integrate a [function] in [range] with additional [features]. * The [function] is placed in the end position to allow passing a lambda. */ @UnstableKMathAPI -public fun UnivariateIntegrator.integrate( +public fun UnivariateIntegrator.integrate( range: ClosedRange, featureBuilder: MutableList.() -> Unit = {}, - function: (Double) -> Double, -): Double { + function: (Double) -> T, +): UnivariateIntegrand { //TODO use dedicated feature builder class instead or add extensions to MutableList val features = buildList { featureBuilder() add(IntegrationRange(range)) } - return integrate( - UnivariateIntegrand(function, *features.toTypedArray()) - ).value ?: error("Unexpected: no value after integration.") + return integrate(UnivariateIntegrand(function, *features.toTypedArray())) } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 195711452..b611b3f65 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -19,7 +19,7 @@ class GaussIntegralTest { val res = DoubleField.integrate(0.0..2 * PI) { x -> sin(x) } - assertEquals(0.0, res.value!!, 1e-2) + assertEquals(0.0, res.valueOrNull!!, 1e-2) } @Test @@ -31,7 +31,7 @@ class GaussIntegralTest { 0.0 } } - assertEquals(20.0, res.value!!, 0.5) + assertEquals(20.0, res.valueOrNull!!, 0.5) } From d1e76175b79bec4e41822cccc596019975e84a89 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 16 May 2021 14:09:21 +0300 Subject: [PATCH 348/393] Refactor integrator API. --- .../kotlin/space/kscience/kmath/functions/integrate.kt | 7 +++++-- .../space/kscience/kmath/functions/matrixIntegration.kt | 7 +++++-- .../kscience/kmath/commons/integration/IntegrationTest.kt | 5 +++-- .../space/kscience/kmath/integration/GaussIntegrator.kt | 6 ++++-- .../space/kscience/kmath/integration/GaussIntegralTest.kt | 4 ++-- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt index 73770726b..8d5349bce 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt @@ -5,6 +5,9 @@ package space.kscience.kmath.functions +import space.kscience.kmath.integration.integrate +import space.kscience.kmath.integration.integrator +import space.kscience.kmath.integration.value import space.kscience.kmath.operations.DoubleField import kotlin.math.pow @@ -13,8 +16,8 @@ fun main() { val function: UnivariateFunction = { x -> 3 * x.pow(2) + 2 * x + 1 } //get the result of the integration - val result = DoubleField.integrate(0.0..10.0, function = function) + val result = DoubleField.integrator.integrate(0.0..10.0, function = function) //the value is nullable because in some cases the integration could not succeed - println(result.valueOrNull) + println(result.value) } \ No newline at end of file diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt index 184672044..601a0e3c4 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt @@ -5,6 +5,9 @@ package space.kscience.kmath.functions +import space.kscience.kmath.integration.integrate +import space.kscience.kmath.integration.integrator +import space.kscience.kmath.integration.value import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.nd import space.kscience.kmath.operations.DoubleField @@ -22,9 +25,9 @@ fun main(): Unit = DoubleField { val function: (Double) -> StructureND = { x: Double -> 3 * number(x).pow(2) + 2 * diagonal(x) + 1 } //get the result of the integration - val result = integrate(0.0..10.0, function = function) + val result = integrator.integrate(0.0..10.0, function = function) //the value is nullable because in some cases the integration could not succeed - println(result.valueOrNull) + println(result.value) } } \ No newline at end of file diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt index 97dc94d1d..c5573fef1 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt @@ -7,6 +7,7 @@ package space.kscience.kmath.commons.integration import org.junit.jupiter.api.Test import space.kscience.kmath.integration.integrate +import space.kscience.kmath.integration.value import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField.sin import kotlin.math.PI @@ -19,7 +20,7 @@ internal class IntegrationTest { @Test fun simpson() { - val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function = function) + val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function = function).value assertTrue { abs(res) < 1e-3 } } @@ -28,7 +29,7 @@ internal class IntegrationTest { val res = CMIntegrator.simpson().integrate(0.0..PI, { targetRelativeAccuracy = 1e-4 targetAbsoluteAccuracy = 1e-4 - }, function) + }, function).value assertTrue { abs(res - 2) < 1e-3 } assertTrue { abs(res - 2) > 1e-12 } } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index d6e716371..0038ca0f2 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -6,7 +6,9 @@ package space.kscience.kmath.integration import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Field -import space.kscience.kmath.structures.* +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.indices /** * Set of univariate integration ranges. First components correspond to ranges themselves, second components to number of @@ -81,7 +83,7 @@ public val Field.integrator: GaussIntegrator get() = GaussIntegrat /** - * Use [integrate] to integrate the function in the current algebra with given [range] and [numPoints] + * Integrate using [intervals] segments with Gauss-Legendre rule of [order] order */ @UnstableKMathAPI public fun GaussIntegrator.integrate( diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index b611b3f65..1f9f7aedf 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -16,7 +16,7 @@ import kotlin.test.assertEquals class GaussIntegralTest { @Test fun gaussSin() { - val res = DoubleField.integrate(0.0..2 * PI) { x -> + val res = DoubleField.integrator.integrate(0.0..2 * PI) { x -> sin(x) } assertEquals(0.0, res.valueOrNull!!, 1e-2) @@ -24,7 +24,7 @@ class GaussIntegralTest { @Test fun gaussUniform() { - val res = DoubleField.integrate(0.0..100.0) { x -> + val res = DoubleField.integrator.integrate(0.0..100.0) { x -> if(x in 30.0..50.0){ 1.0 } else { From f86a6130e037cb921713db925b310515338da184 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 16 May 2021 14:20:28 +0300 Subject: [PATCH 349/393] Add opt-in for examples --- examples/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 1c7caf1b9..90bb935b9 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -57,7 +57,7 @@ kotlin.sourceSets.all { tasks.withType { kotlinOptions{ jvmTarget = "11" - freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" } } From eb3a8655fbf229db782be8345cd54413fe305d35 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 15 May 2021 02:23:28 +0700 Subject: [PATCH 350/393] Code generation of EJML linear spaces --- buildSrc/build.gradle.kts | 5 + .../kmath/ejml/codegen/ejmlCodegen.kt | 415 ++++++++ .../kscience/kmath/linear/MatrixFeatures.kt | 17 + kmath-ejml/build.gradle.kts | 22 +- .../kscience/kmath/ejml/EjmlLinearSpace.kt | 223 +--- .../space/kscience/kmath/ejml/EjmlMatrix.kt | 10 - .../space/kscience/kmath/ejml/EjmlVector.kt | 14 +- .../space/kscience/kmath/ejml/_generated.kt | 995 ++++++++++++++++++ .../kscience/kmath/ejml/EjmlVectorTest.kt | 6 +- 9 files changed, 1457 insertions(+), 250 deletions(-) create mode 100644 buildSrc/build.gradle.kts create mode 100644 buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt create mode 100644 kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 000000000..7ca4df19d --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,5 @@ +plugins { + `kotlin-dsl` +} + +repositories.mavenCentral() diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt new file mode 100644 index 000000000..e4b157973 --- /dev/null +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt @@ -0,0 +1,415 @@ +/* + * 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. + */ + +@file:Suppress("KDocUnresolvedReference") + +package space.kscience.kmath.ejml.codegen + +import org.intellij.lang.annotations.Language +import java.io.File + +private fun Appendable.appendEjmlVector(type: String, ejmlMatrixType: String) { + @Language("kotlin") val text = """/** + * [EjmlVector] specialization for [$type]. + */ +public class Ejml${type}Vector(public override val origin: M) : EjmlVector<$type, M>(origin) { + init { + require(origin.numRows == 1) { "The origin matrix must have only one row to form a vector" } + } + + public override operator fun get(index: Int): $type = origin[0, index] +}""" + appendLine(text) + appendLine() +} + +private fun Appendable.appendEjmlMatrix(type: String, ejmlMatrixType: String) { + val text = """/** + * [EjmlMatrix] specialization for [$type]. + */ +public class Ejml${type}Matrix(public override val origin: M) : EjmlMatrix<$type, M>(origin) { + public override operator fun get(i: Int, j: Int): $type = origin[i, j] +}""" + appendLine(text) + appendLine() +} + +private fun Appendable.appendEjmlLinearSpace( + type: String, + kmathAlgebra: String, + ejmlMatrixParentTypeMatrix: String, + ejmlMatrixType: String, + ejmlMatrixDenseType: String, + ops: String, + denseOps: String, + isDense: Boolean, +) { + @Language("kotlin") val text = """/** + * [EjmlLinearSpace] implementation based on [CommonOps_$ops], [DecompositionFactory_${ops}] operations and + * [${ejmlMatrixType}] matrices. + */ +public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra}, $ejmlMatrixType>() { + /** + * The [${kmathAlgebra}] reference. + */ + public override val elementAlgebra: $kmathAlgebra get() = $kmathAlgebra + + @Suppress("UNCHECKED_CAST") + public override fun Matrix<${type}>.toEjml(): Ejml${type}Matrix<${ejmlMatrixType}> = when { + this is Ejml${type}Matrix<*> && origin is $ejmlMatrixType -> this as Ejml${type}Matrix<${ejmlMatrixType}> + else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } + } + + @Suppress("UNCHECKED_CAST") + public override fun Point<${type}>.toEjml(): Ejml${type}Vector<${ejmlMatrixType}> = when { + this is Ejml${type}Vector<*> && origin is $ejmlMatrixType -> this as Ejml${type}Vector<${ejmlMatrixType}> + else -> Ejml${type}Vector(${ejmlMatrixType}(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } + }) + } + + public override fun buildMatrix( + rows: Int, + columns: Int, + initializer: ${kmathAlgebra}.(i: Int, j: Int) -> ${type}, + ): Ejml${type}Matrix<${ejmlMatrixType}> = ${ejmlMatrixType}(rows, columns).also { + (0 until rows).forEach { row -> + (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } + } + }.wrapMatrix() + + public override fun buildVector( + size: Int, + initializer: ${kmathAlgebra}.(Int) -> ${type}, + ): Ejml${type}Vector<${ejmlMatrixType}> = Ejml${type}Vector(${ejmlMatrixType}(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } + }) + + private fun T.wrapMatrix() = Ejml${type}Matrix(this) + private fun T.wrapVector() = Ejml${type}Vector(this) + + public override fun Matrix<${type}>.unaryMinus(): Matrix<${type}> = this * elementAlgebra { -one } + + public override fun Matrix<${type}>.dot(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> { + val out = ${ejmlMatrixType}(1, 1) + CommonOps_${ops}.mult(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } + + public override fun Matrix<${type}>.dot(vector: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> { + val out = ${ejmlMatrixType}(1, 1) + CommonOps_${ops}.mult(toEjml().origin, vector.toEjml().origin, out) + return out.wrapVector() + } + + public override operator fun Matrix<${type}>.minus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> { + val out = ${ejmlMatrixType}(1, 1) + + CommonOps_${ops}.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out,${ + if (isDense) "" else + """ + null, + null,""" + } + ) + + return out.wrapMatrix() + } + + public override operator fun Matrix<${type}>.times(value: ${type}): Ejml${type}Matrix<${ejmlMatrixType}> { + val res = ${ejmlMatrixType}(1, 1) + CommonOps_${ops}.scale(value, toEjml().origin, res) + return res.wrapMatrix() + } + + public override fun Point<${type}>.unaryMinus(): Ejml${type}Vector<${ejmlMatrixType}> { + val res = ${ejmlMatrixType}(1, 1) + CommonOps_${ops}.changeSign(toEjml().origin, res) + return res.wrapVector() + } + + public override fun Matrix<${type}>.plus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> { + val out = ${ejmlMatrixType}(1, 1) + + CommonOps_${ops}.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out,${ + if (isDense) "" else + """ + null, + null,""" + } + ) + + return out.wrapMatrix() + } + + public override fun Point<${type}>.plus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> { + val out = ${ejmlMatrixType}(1, 1) + + CommonOps_${ops}.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out,${ + if (isDense) "" else + """ + null, + null,""" + } + ) + + return out.wrapVector() + } + + public override fun Point<${type}>.minus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> { + val out = ${ejmlMatrixType}(1, 1) + + CommonOps_${ops}.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out,${ + if (isDense) "" else + """ + null, + null,""" + } + ) + + return out.wrapVector() + } + + public override fun ${type}.times(m: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> = m * this + + public override fun Point<${type}>.times(value: ${type}): Ejml${type}Vector<${ejmlMatrixType}> { + val res = ${ejmlMatrixType}(1, 1) + CommonOps_${ops}.scale(value, toEjml().origin, res) + return res.wrapVector() + } + + public override fun ${type}.times(v: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> = v * this + + @UnstableKMathAPI + public override fun getFeature(structure: Matrix<${type}>, type: KClass): F? { + structure.getFeature(type)?.let { return it } + val origin = structure.toEjml().origin + + return when (type) { + ${ + if (isDense) + """ InverseMatrixFeature::class -> object : InverseMatrixFeature<${type}> { + override val inverse: Matrix<${type}> by lazy { + val res = origin.copy() + CommonOps_${ops}.invert(res) + res.wrapMatrix() + } + } + + DeterminantFeature::class -> object : DeterminantFeature<${type}> { + override val determinant: $type by lazy { CommonOps_${ops}.det(origin) } + } + + SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<${type}> { + private val svd by lazy { + DecompositionFactory_${ops}.svd(origin.numRows, origin.numCols, true, true, false) + .apply { decompose(origin.copy()) } + } + + override val u: Matrix<${type}> by lazy { svd.getU(null, false).wrapMatrix() } + override val s: Matrix<${type}> by lazy { svd.getW(null).wrapMatrix() } + override val v: Matrix<${type}> by lazy { svd.getV(null, false).wrapMatrix() } + override val singularValues: Point<${type}> by lazy { ${type}Buffer(svd.singularValues) } + } + + QRDecompositionFeature::class -> object : QRDecompositionFeature<${type}> { + private val qr by lazy { + DecompositionFactory_${ops}.qr().apply { decompose(origin.copy()) } + } + + override val q: Matrix<${type}> by lazy { + qr.getQ(null, false).wrapMatrix() + OrthogonalFeature + } + + override val r: Matrix<${type}> by lazy { qr.getR(null, false).wrapMatrix() + UFeature } + } + + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<${type}> { + override val l: Matrix<${type}> by lazy { + val cholesky = + DecompositionFactory_${ops}.chol(structure.rowNum, true).apply { decompose(origin.copy()) } + + cholesky.getT(null).wrapMatrix() + LFeature + } + } + + LupDecompositionFeature::class -> object : LupDecompositionFeature<${type}> { + private val lup by lazy { + DecompositionFactory_${ops}.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) } + } + + override val l: Matrix<${type}> by lazy { + lup.getLower(null).wrapMatrix() + LFeature + } + + override val u: Matrix<${type}> by lazy { + lup.getUpper(null).wrapMatrix() + UFeature + } + + override val p: Matrix<${type}> by lazy { lup.getRowPivot(null).wrapMatrix() } + }""" else """ QRDecompositionFeature::class -> object : QRDecompositionFeature<$type> { + private val qr by lazy { + DecompositionFactory_${ops}.qr(FillReducing.NONE).apply { decompose(origin.copy()) } + } + + override val q: Matrix<${type}> by lazy { + qr.getQ(null, false).wrapMatrix() + OrthogonalFeature + } + + override val r: Matrix<${type}> by lazy { qr.getR(null, false).wrapMatrix() + UFeature } + } + + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<${type}> { + override val l: Matrix<${type}> by lazy { + val cholesky = + DecompositionFactory_${ops}.cholesky().apply { decompose(origin.copy()) } + + (cholesky.getT(null) as ${ejmlMatrixParentTypeMatrix}).wrapMatrix() + LFeature + } + } + + LUDecompositionFeature::class, DeterminantFeature::class, InverseMatrixFeature::class -> object : + LUDecompositionFeature<${type}>, DeterminantFeature<${type}>, InverseMatrixFeature<${type}> { + private val lu by lazy { + DecompositionFactory_${ops}.lu(FillReducing.NONE).apply { decompose(origin.copy()) } + } + + override val l: Matrix<${type}> by lazy { + lu.getLower(null).wrapMatrix() + LFeature + } + + override val u: Matrix<${type}> by lazy { + lu.getUpper(null).wrapMatrix() + UFeature + } + + override val inverse: Matrix<${type}> by lazy { + var a = origin + val inverse = ${ejmlMatrixDenseType}(1, 1) + val solver = LinearSolverFactory_${ops}.lu(FillReducing.NONE) + if (solver.modifiesA()) a = a.copy() + val i = CommonOps_${denseOps}.identity(a.numRows) + solver.solve(i, inverse) + inverse.wrapMatrix() + } + + override val determinant: $type by lazy { elementAlgebra.number(lu.computeDeterminant().real) } + }""" + } + + else -> null + }?.let(type::cast) + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix<${type}>, b: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> { + val res = ${ejmlMatrixType}(1, 1) + CommonOps_${ops}.solve(${ejmlMatrixType}(a.toEjml().origin), ${ejmlMatrixType}(b.toEjml().origin), res) + return res.wrapMatrix() + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix<${type}>, b: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> { + val res = ${ejmlMatrixType}(1, 1) + CommonOps_${ops}.solve(${ejmlMatrixType}(a.toEjml().origin), ${ejmlMatrixType}(b.toEjml().origin), res) + return Ejml${type}Vector(res) + } +}""" + appendLine(text) + appendLine() +} + + +/** + * Generates routine EJML classes. + */ +fun ejmlCodegen(outputFile: String): Unit = File(outputFile).run { + parentFile.mkdirs() + + writer().use { + it.appendLine("/*") + it.appendLine(" * Copyright 2018-2021 KMath contributors.") + it.appendLine(" * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.") + it.appendLine(" */") + it.appendLine() + it.appendLine("/* This file is generated with buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt */") + it.appendLine() + it.appendLine("package space.kscience.kmath.ejml") + it.appendLine() + it.appendLine("import org.ejml.data.*") + it.appendLine("import space.kscience.kmath.linear.*") + it.appendLine("import space.kscience.kmath.operations.*") + it.appendLine("import space.kscience.kmath.structures.*") + it.appendLine("import space.kscience.kmath.misc.*") + it.appendLine("import kotlin.reflect.*") + it.appendLine("import org.ejml.dense.row.*") + it.appendLine("import org.ejml.dense.row.factory.*") + it.appendLine("import org.ejml.sparse.*") + it.appendLine("import org.ejml.sparse.csc.*") + it.appendLine("import org.ejml.sparse.csc.factory.*") + it.appendLine("import space.kscience.kmath.nd.*") + it.appendLine("import space.kscience.kmath.linear.Matrix") + it.appendLine() + it.appendEjmlVector("Double", "DMatrix") + it.appendEjmlVector("Float", "FMatrix") + it.appendEjmlMatrix("Double", "DMatrix") + it.appendEjmlMatrix("Float", "FMatrix") + it.appendEjmlLinearSpace("Double", "DoubleField", "DMatrix", "DMatrixRMaj", "DMatrixRMaj", "DDRM", "DDRM", true) + it.appendEjmlLinearSpace("Float", "FloatField", "FMatrix", "FMatrixRMaj", "FMatrixRMaj", "FDRM", "FDRM", true) + + it.appendEjmlLinearSpace( + type = "Double", + kmathAlgebra = "DoubleField", + ejmlMatrixParentTypeMatrix = "DMatrix", + ejmlMatrixType = "DMatrixSparseCSC", + ejmlMatrixDenseType = "DMatrixRMaj", + ops = "DSCC", + denseOps = "DDRM", + isDense = false, + ) + + it.appendEjmlLinearSpace( + type = "Float", + kmathAlgebra = "FloatField", + ejmlMatrixParentTypeMatrix = "FMatrix", + ejmlMatrixType = "FMatrixSparseCSC", + ejmlMatrixDenseType = "FMatrixRMaj", + ops = "FSCC", + denseOps = "FDRM", + isDense = false, + ) + } +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt index 4a0ca7dfe..37c93d249 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt @@ -75,6 +75,23 @@ public object LFeature : MatrixFeature */ public object UFeature : MatrixFeature +/** + * Matrices with this feature support LU factorization: *a = [l] · [u]* where *a* is the owning matrix. + * + * @param T the type of matrices' items. + */ +public interface LUDecompositionFeature : MatrixFeature { + /** + * The lower triangular matrix in this decomposition. It may have [LFeature]. + */ + public val l: Matrix + + /** + * The upper triangular matrix in this decomposition. It may have [UFeature]. + */ + public val u: Matrix +} + /** * Matrices with this feature support LU factorization with partial pivoting: *[p] · a = [l] · [u]* where * *a* is the owning matrix. diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index c8e2ecd8b..5107cfb68 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -1,3 +1,5 @@ +import space.kscience.kmath.ejml.codegen.ejmlCodegen + plugins { kotlin("jvm") id("ru.mipt.npm.gradle.common") @@ -5,6 +7,9 @@ plugins { dependencies { api("org.ejml:ejml-ddense:0.40") + api("org.ejml:ejml-fdense:0.40") + api("org.ejml:ejml-dsparse:0.40") + api("org.ejml:ejml-fsparse:0.40") api(project(":kmath-core")) } @@ -14,19 +19,24 @@ readme { feature( id = "ejml-vector", - description = "Point implementations.", ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt" - ) + ) { "Point implementations." } feature( id = "ejml-matrix", - description = "Matrix implementation.", ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt" - ) + ) { "Matrix implementation." } feature( id = "ejml-linear-space", - description = "LinearSpace implementations.", ref = "src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt" - ) + ) { "LinearSpace implementations." } +} + +kotlin.sourceSets.main { + val codegen by tasks.creating { + ejmlCodegen(kotlin.srcDirs.first().absolutePath + "/space/kscience/kmath/ejml/_generated.kt") + } + + kotlin.srcDirs(files().builtBy(codegen)) } diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index 71cae4829..f88e83369 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -5,19 +5,10 @@ package space.kscience.kmath.ejml -import org.ejml.data.DMatrix -import org.ejml.data.DMatrixD1 -import org.ejml.data.DMatrixRMaj -import org.ejml.dense.row.CommonOps_DDRM -import org.ejml.dense.row.factory.DecompositionFactory_DDRM -import space.kscience.kmath.linear.* -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.StructureFeature -import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.linear.LinearSpace +import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.linear.Point import space.kscience.kmath.operations.Ring -import space.kscience.kmath.structures.DoubleBuffer -import kotlin.reflect.KClass -import kotlin.reflect.cast /** * [LinearSpace] implementation specialized for a certain EJML type. @@ -27,7 +18,7 @@ import kotlin.reflect.cast * @param M the EJML matrix type. * @author Iaroslav Postovalov */ -public abstract class EjmlLinearSpace, M : org.ejml.data.Matrix> : LinearSpace { +public abstract class EjmlLinearSpace, out M : org.ejml.data.Matrix> : LinearSpace { /** * Converts this matrix to EJML one. */ @@ -46,209 +37,3 @@ public abstract class EjmlLinearSpace, M : org.ejml.dat public abstract override fun buildVector(size: Int, initializer: A.(Int) -> T): EjmlVector } - -/** - * [EjmlLinearSpace] implementation based on [CommonOps_DDRM], [DecompositionFactory_DDRM] operations and - * [DMatrixRMaj] matrices. - * - * @author Iaroslav Postovalov - */ -public object EjmlLinearSpaceDDRM : EjmlLinearSpace() { - /** - * The [DoubleField] reference. - */ - public override val elementAlgebra: DoubleField get() = DoubleField - - @Suppress("UNCHECKED_CAST") - public override fun Matrix.toEjml(): EjmlDoubleMatrix = when { - this is EjmlDoubleMatrix<*> && origin is DMatrixRMaj -> this as EjmlDoubleMatrix - else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } - } - - @Suppress("UNCHECKED_CAST") - public override fun Point.toEjml(): EjmlDoubleVector = when { - this is EjmlDoubleVector<*> && origin is DMatrixRMaj -> this as EjmlDoubleVector - else -> EjmlDoubleVector(DMatrixRMaj(size, 1).also { - (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } - }) - } - - public override fun buildMatrix( - rows: Int, - columns: Int, - initializer: DoubleField.(i: Int, j: Int) -> Double, - ): EjmlDoubleMatrix = EjmlDoubleMatrix(DMatrixRMaj(rows, columns).also { - (0 until rows).forEach { row -> - (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } - } - }) - - public override fun buildVector( - size: Int, - initializer: DoubleField.(Int) -> Double, - ): EjmlDoubleVector = EjmlDoubleVector(DMatrixRMaj(size, 1).also { - (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } - }) - - private fun T.wrapMatrix() = EjmlDoubleMatrix(this) - private fun T.wrapVector() = EjmlDoubleVector(this) - - public override fun Matrix.unaryMinus(): Matrix = this * (-1.0) - - public override fun Matrix.dot(other: Matrix): EjmlDoubleMatrix { - val out = DMatrixRMaj(1, 1) - CommonOps_DDRM.mult(toEjml().origin, other.toEjml().origin, out) - return out.wrapMatrix() - } - - public override fun Matrix.dot(vector: Point): EjmlDoubleVector { - val out = DMatrixRMaj(1, 1) - CommonOps_DDRM.mult(toEjml().origin, vector.toEjml().origin, out) - return out.wrapVector() - } - - public override operator fun Matrix.minus(other: Matrix): EjmlDoubleMatrix { - val out = DMatrixRMaj(1, 1) - CommonOps_DDRM.subtract(toEjml().origin, other.toEjml().origin, out) - return out.wrapMatrix() - } - - public override operator fun Matrix.times(value: Double): EjmlDoubleMatrix { - val res = this.toEjml().origin.copy() - CommonOps_DDRM.scale(value, res) - return res.wrapMatrix() - } - - public override fun Point.unaryMinus(): EjmlDoubleVector { - val out = toEjml().origin.copy() - CommonOps_DDRM.changeSign(out) - return out.wrapVector() - } - - public override fun Matrix.plus(other: Matrix): EjmlDoubleMatrix { - val out = DMatrixRMaj(1, 1) - CommonOps_DDRM.add(toEjml().origin, other.toEjml().origin, out) - return out.wrapMatrix() - } - - public override fun Point.plus(other: Point): EjmlDoubleVector { - val out = DMatrixRMaj(1, 1) - CommonOps_DDRM.add(toEjml().origin, other.toEjml().origin, out) - return out.wrapVector() - } - - public override fun Point.minus(other: Point): EjmlDoubleVector { - val out = DMatrixRMaj(1, 1) - CommonOps_DDRM.subtract(toEjml().origin, other.toEjml().origin, out) - return out.wrapVector() - } - - public override fun Double.times(m: Matrix): EjmlDoubleMatrix = m * this - - public override fun Point.times(value: Double): EjmlDoubleVector { - val res = this.toEjml().origin.copy() - CommonOps_DDRM.scale(value, res) - return res.wrapVector() - } - - public override fun Double.times(v: Point): EjmlDoubleVector = v * this - - @UnstableKMathAPI - public override fun getFeature(structure: Matrix, type: KClass): F? { - // Return the feature if it is intrinsic to the structure - structure.getFeature(type)?.let { return it } - - val origin = structure.toEjml().origin - - return when (type) { - InverseMatrixFeature::class -> object : InverseMatrixFeature { - override val inverse: Matrix by lazy { - val res = origin.copy() - CommonOps_DDRM.invert(res) - EjmlDoubleMatrix(res) - } - } - - DeterminantFeature::class -> object : DeterminantFeature { - override val determinant: Double by lazy { CommonOps_DDRM.det(DMatrixRMaj(origin)) } - } - - SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { - private val svd by lazy { - DecompositionFactory_DDRM.svd(origin.numRows, origin.numCols, true, true, false) - .apply { decompose(origin.copy()) } - } - - override val u: Matrix by lazy { EjmlDoubleMatrix(svd.getU(null, false)) } - override val s: Matrix by lazy { EjmlDoubleMatrix(svd.getW(null)) } - override val v: Matrix by lazy { EjmlDoubleMatrix(svd.getV(null, false)) } - override val singularValues: Point by lazy { DoubleBuffer(svd.singularValues) } - } - - QRDecompositionFeature::class -> object : QRDecompositionFeature { - private val qr by lazy { - DecompositionFactory_DDRM.qr().apply { decompose(origin.copy()) } - } - - override val q: Matrix by lazy { - EjmlDoubleMatrix(qr.getQ(null, false)) + OrthogonalFeature - } - - override val r: Matrix by lazy { EjmlDoubleMatrix(qr.getR(null, false)) + UFeature } - } - - CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { - override val l: Matrix by lazy { - val cholesky = - DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) } - - EjmlDoubleMatrix(cholesky.getT(null)) + LFeature - } - } - - LupDecompositionFeature::class -> object : LupDecompositionFeature { - private val lup by lazy { - DecompositionFactory_DDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) } - } - - override val l: Matrix by lazy { - EjmlDoubleMatrix(lup.getLower(null)) + LFeature - } - - override val u: Matrix by lazy { - EjmlDoubleMatrix(lup.getUpper(null)) + UFeature - } - - override val p: Matrix by lazy { EjmlDoubleMatrix(lup.getRowPivot(null)) } - } - - else -> null - }?.let(type::cast) - } - - /** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p matrix. - * @return the solution for 'x' that is n by p. - */ - public fun solve(a: Matrix, b: Matrix): EjmlDoubleMatrix { - val res = DMatrixRMaj(1, 1) - CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res) - return EjmlDoubleMatrix(res) - } - - /** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p vector. - * @return the solution for 'x' that is n by p. - */ - public fun solve(a: Matrix, b: Point): EjmlDoubleVector { - val res = DMatrixRMaj(1, 1) - CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res) - return EjmlDoubleVector(res) - } -} diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index 92c4d1cf0..fd43f295c 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.ejml -import org.ejml.data.DMatrix import org.ejml.data.Matrix import space.kscience.kmath.nd.Structure2D @@ -21,12 +20,3 @@ public abstract class EjmlMatrix(public open val origin: M) : public override val rowNum: Int get() = origin.numRows public override val colNum: Int get() = origin.numCols } - -/** - * [EjmlMatrix] specialization for [Double]. - * - * @author Iaroslav Postovalov - */ -public class EjmlDoubleMatrix(public override val origin: M) : EjmlMatrix(origin) { - public override operator fun get(i: Int, j: Int): Double = origin[i, j] -} diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt index 81502d6d0..5d10d1fbb 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.ejml -import org.ejml.data.DMatrixD1 import org.ejml.data.Matrix import space.kscience.kmath.linear.Point @@ -14,12 +13,12 @@ import space.kscience.kmath.linear.Point * * @param T the type of elements contained in the buffer. * @param M the type of EJML matrix. - * @property origin The underlying matrix. + * @property origin The underlying matrix, must have only one row. * @author Iaroslav Postovalov */ public abstract class EjmlVector(public open val origin: M) : Point { public override val size: Int - get() = origin.numRows + get() = origin.numCols public override operator fun iterator(): Iterator = object : Iterator { private var cursor: Int = 0 @@ -34,12 +33,3 @@ public abstract class EjmlVector(public open val origin: public override fun toString(): String = "EjmlVector(origin=$origin)" } - -/** - * [EjmlVector] specialization for [Double]. - * - * @author Iaroslav Postovalov - */ -public class EjmlDoubleVector(public override val origin: M) : EjmlVector(origin) { - public override operator fun get(index: Int): Double = origin[index] -} diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt new file mode 100644 index 000000000..139c55697 --- /dev/null +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt @@ -0,0 +1,995 @@ +/* + * 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. + */ + +/* This file is generated with buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt */ + +package space.kscience.kmath.ejml + +import org.ejml.data.* +import org.ejml.dense.row.CommonOps_DDRM +import org.ejml.dense.row.CommonOps_FDRM +import org.ejml.dense.row.factory.DecompositionFactory_DDRM +import org.ejml.dense.row.factory.DecompositionFactory_FDRM +import org.ejml.sparse.FillReducing +import org.ejml.sparse.csc.CommonOps_DSCC +import org.ejml.sparse.csc.CommonOps_FSCC +import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC +import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC +import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC +import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC +import space.kscience.kmath.linear.* +import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.StructureFeature +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.FloatField +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.FloatBuffer +import kotlin.reflect.KClass +import kotlin.reflect.cast + +/** + * [EjmlVector] specialization for [Double]. + */ +public class EjmlDoubleVector(public override val origin: M) : EjmlVector(origin) { + init { + require(origin.numRows == 1) { "The origin matrix must have only one row to form a vector" } + } + + public override operator fun get(index: Int): Double = origin[0, index] +} + +/** + * [EjmlVector] specialization for [Float]. + */ +public class EjmlFloatVector(public override val origin: M) : EjmlVector(origin) { + init { + require(origin.numRows == 1) { "The origin matrix must have only one row to form a vector" } + } + + public override operator fun get(index: Int): Float = origin[0, index] +} + +/** + * [EjmlMatrix] specialization for [Double]. + */ +public class EjmlDoubleMatrix(public override val origin: M) : EjmlMatrix(origin) { + public override operator fun get(i: Int, j: Int): Double = origin[i, j] +} + +/** + * [EjmlMatrix] specialization for [Float]. + */ +public class EjmlFloatMatrix(public override val origin: M) : EjmlMatrix(origin) { + public override operator fun get(i: Int, j: Int): Float = origin[i, j] +} + +/** + * [EjmlLinearSpace] implementation based on [CommonOps_DDRM], [DecompositionFactory_DDRM] operations and + * [DMatrixRMaj] matrices. + */ +public object EjmlLinearSpaceDDRM : EjmlLinearSpace() { + /** + * The [DoubleField] reference. + */ + public override val elementAlgebra: DoubleField get() = DoubleField + + @Suppress("UNCHECKED_CAST") + public override fun Matrix.toEjml(): EjmlDoubleMatrix = when { + this is EjmlDoubleMatrix<*> && origin is DMatrixRMaj -> this as EjmlDoubleMatrix + else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } + } + + @Suppress("UNCHECKED_CAST") + public override fun Point.toEjml(): EjmlDoubleVector = when { + this is EjmlDoubleVector<*> && origin is DMatrixRMaj -> this as EjmlDoubleVector + else -> EjmlDoubleVector(DMatrixRMaj(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } + }) + } + + public override fun buildMatrix( + rows: Int, + columns: Int, + initializer: DoubleField.(i: Int, j: Int) -> Double, + ): EjmlDoubleMatrix = DMatrixRMaj(rows, columns).also { + (0 until rows).forEach { row -> + (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } + } + }.wrapMatrix() + + public override fun buildVector( + size: Int, + initializer: DoubleField.(Int) -> Double, + ): EjmlDoubleVector = EjmlDoubleVector(DMatrixRMaj(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } + }) + + private fun T.wrapMatrix() = EjmlDoubleMatrix(this) + private fun T.wrapVector() = EjmlDoubleVector(this) + + public override fun Matrix.unaryMinus(): Matrix = this * elementAlgebra { -one } + + public override fun Matrix.dot(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.mult(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } + + public override fun Matrix.dot(vector: Point): EjmlDoubleVector { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.mult(toEjml().origin, vector.toEjml().origin, out) + return out.wrapVector() + } + + public override operator fun Matrix.minus(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixRMaj(1, 1) + + CommonOps_DDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + ) + + return out.wrapMatrix() + } + + public override operator fun Matrix.times(value: Double): EjmlDoubleMatrix { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.scale(value, toEjml().origin, res) + return res.wrapMatrix() + } + + public override fun Point.unaryMinus(): EjmlDoubleVector { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.changeSign(toEjml().origin, res) + return res.wrapVector() + } + + public override fun Matrix.plus(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixRMaj(1, 1) + + CommonOps_DDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + ) + + return out.wrapMatrix() + } + + public override fun Point.plus(other: Point): EjmlDoubleVector { + val out = DMatrixRMaj(1, 1) + + CommonOps_DDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + ) + + return out.wrapVector() + } + + public override fun Point.minus(other: Point): EjmlDoubleVector { + val out = DMatrixRMaj(1, 1) + + CommonOps_DDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + ) + + return out.wrapVector() + } + + public override fun Double.times(m: Matrix): EjmlDoubleMatrix = m * this + + public override fun Point.times(value: Double): EjmlDoubleVector { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.scale(value, toEjml().origin, res) + return res.wrapVector() + } + + public override fun Double.times(v: Point): EjmlDoubleVector = v * this + + @UnstableKMathAPI + public override fun getFeature(structure: Matrix, type: KClass): F? { + structure.getFeature(type)?.let { return it } + val origin = structure.toEjml().origin + + return when (type) { + InverseMatrixFeature::class -> object : InverseMatrixFeature { + override val inverse: Matrix by lazy { + val res = origin.copy() + CommonOps_DDRM.invert(res) + res.wrapMatrix() + } + } + + DeterminantFeature::class -> object : DeterminantFeature { + override val determinant: Double by lazy { CommonOps_DDRM.det(origin) } + } + + SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { + private val svd by lazy { + DecompositionFactory_DDRM.svd(origin.numRows, origin.numCols, true, true, false) + .apply { decompose(origin.copy()) } + } + + override val u: Matrix by lazy { svd.getU(null, false).wrapMatrix() } + override val s: Matrix by lazy { svd.getW(null).wrapMatrix() } + override val v: Matrix by lazy { svd.getV(null, false).wrapMatrix() } + override val singularValues: Point by lazy { DoubleBuffer(svd.singularValues) } + } + + QRDecompositionFeature::class -> object : QRDecompositionFeature { + private val qr by lazy { + DecompositionFactory_DDRM.qr().apply { decompose(origin.copy()) } + } + + override val q: Matrix by lazy { + qr.getQ(null, false).wrapMatrix() + OrthogonalFeature + } + + override val r: Matrix by lazy { qr.getR(null, false).wrapMatrix() + UFeature } + } + + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { + override val l: Matrix by lazy { + val cholesky = + DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) } + + cholesky.getT(null).wrapMatrix() + LFeature + } + } + + LupDecompositionFeature::class -> object : LupDecompositionFeature { + private val lup by lazy { + DecompositionFactory_DDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) } + } + + override val l: Matrix by lazy { + lup.getLower(null).wrapMatrix() + LFeature + } + + override val u: Matrix by lazy { + lup.getUpper(null).wrapMatrix() + UFeature + } + + override val p: Matrix by lazy { lup.getRowPivot(null).wrapMatrix() } + } + + else -> null + }?.let(type::cast) + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Matrix): EjmlDoubleMatrix { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res) + return res.wrapMatrix() + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Point): EjmlDoubleVector { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res) + return EjmlDoubleVector(res) + } +} + +/** + * [EjmlLinearSpace] implementation based on [CommonOps_FDRM], [DecompositionFactory_FDRM] operations and + * [FMatrixRMaj] matrices. + */ +public object EjmlLinearSpaceFDRM : EjmlLinearSpace() { + /** + * The [FloatField] reference. + */ + public override val elementAlgebra: FloatField get() = FloatField + + @Suppress("UNCHECKED_CAST") + public override fun Matrix.toEjml(): EjmlFloatMatrix = when { + this is EjmlFloatMatrix<*> && origin is FMatrixRMaj -> this as EjmlFloatMatrix + else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } + } + + @Suppress("UNCHECKED_CAST") + public override fun Point.toEjml(): EjmlFloatVector = when { + this is EjmlFloatVector<*> && origin is FMatrixRMaj -> this as EjmlFloatVector + else -> EjmlFloatVector(FMatrixRMaj(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } + }) + } + + public override fun buildMatrix( + rows: Int, + columns: Int, + initializer: FloatField.(i: Int, j: Int) -> Float, + ): EjmlFloatMatrix = FMatrixRMaj(rows, columns).also { + (0 until rows).forEach { row -> + (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } + } + }.wrapMatrix() + + public override fun buildVector( + size: Int, + initializer: FloatField.(Int) -> Float, + ): EjmlFloatVector = EjmlFloatVector(FMatrixRMaj(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } + }) + + private fun T.wrapMatrix() = EjmlFloatMatrix(this) + private fun T.wrapVector() = EjmlFloatVector(this) + + public override fun Matrix.unaryMinus(): Matrix = this * elementAlgebra { -one } + + public override fun Matrix.dot(other: Matrix): EjmlFloatMatrix { + val out = FMatrixRMaj(1, 1) + CommonOps_FDRM.mult(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } + + public override fun Matrix.dot(vector: Point): EjmlFloatVector { + val out = FMatrixRMaj(1, 1) + CommonOps_FDRM.mult(toEjml().origin, vector.toEjml().origin, out) + return out.wrapVector() + } + + public override operator fun Matrix.minus(other: Matrix): EjmlFloatMatrix { + val out = FMatrixRMaj(1, 1) + + CommonOps_FDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + ) + + return out.wrapMatrix() + } + + public override operator fun Matrix.times(value: Float): EjmlFloatMatrix { + val res = FMatrixRMaj(1, 1) + CommonOps_FDRM.scale(value, toEjml().origin, res) + return res.wrapMatrix() + } + + public override fun Point.unaryMinus(): EjmlFloatVector { + val res = FMatrixRMaj(1, 1) + CommonOps_FDRM.changeSign(toEjml().origin, res) + return res.wrapVector() + } + + public override fun Matrix.plus(other: Matrix): EjmlFloatMatrix { + val out = FMatrixRMaj(1, 1) + + CommonOps_FDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + ) + + return out.wrapMatrix() + } + + public override fun Point.plus(other: Point): EjmlFloatVector { + val out = FMatrixRMaj(1, 1) + + CommonOps_FDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + ) + + return out.wrapVector() + } + + public override fun Point.minus(other: Point): EjmlFloatVector { + val out = FMatrixRMaj(1, 1) + + CommonOps_FDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + ) + + return out.wrapVector() + } + + public override fun Float.times(m: Matrix): EjmlFloatMatrix = m * this + + public override fun Point.times(value: Float): EjmlFloatVector { + val res = FMatrixRMaj(1, 1) + CommonOps_FDRM.scale(value, toEjml().origin, res) + return res.wrapVector() + } + + public override fun Float.times(v: Point): EjmlFloatVector = v * this + + @UnstableKMathAPI + public override fun getFeature(structure: Matrix, type: KClass): F? { + structure.getFeature(type)?.let { return it } + val origin = structure.toEjml().origin + + return when (type) { + InverseMatrixFeature::class -> object : InverseMatrixFeature { + override val inverse: Matrix by lazy { + val res = origin.copy() + CommonOps_FDRM.invert(res) + res.wrapMatrix() + } + } + + DeterminantFeature::class -> object : DeterminantFeature { + override val determinant: Float by lazy { CommonOps_FDRM.det(origin) } + } + + SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { + private val svd by lazy { + DecompositionFactory_FDRM.svd(origin.numRows, origin.numCols, true, true, false) + .apply { decompose(origin.copy()) } + } + + override val u: Matrix by lazy { svd.getU(null, false).wrapMatrix() } + override val s: Matrix by lazy { svd.getW(null).wrapMatrix() } + override val v: Matrix by lazy { svd.getV(null, false).wrapMatrix() } + override val singularValues: Point by lazy { FloatBuffer(svd.singularValues) } + } + + QRDecompositionFeature::class -> object : QRDecompositionFeature { + private val qr by lazy { + DecompositionFactory_FDRM.qr().apply { decompose(origin.copy()) } + } + + override val q: Matrix by lazy { + qr.getQ(null, false).wrapMatrix() + OrthogonalFeature + } + + override val r: Matrix by lazy { qr.getR(null, false).wrapMatrix() + UFeature } + } + + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { + override val l: Matrix by lazy { + val cholesky = + DecompositionFactory_FDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) } + + cholesky.getT(null).wrapMatrix() + LFeature + } + } + + LupDecompositionFeature::class -> object : LupDecompositionFeature { + private val lup by lazy { + DecompositionFactory_FDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) } + } + + override val l: Matrix by lazy { + lup.getLower(null).wrapMatrix() + LFeature + } + + override val u: Matrix by lazy { + lup.getUpper(null).wrapMatrix() + UFeature + } + + override val p: Matrix by lazy { lup.getRowPivot(null).wrapMatrix() } + } + + else -> null + }?.let(type::cast) + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Matrix): EjmlFloatMatrix { + val res = FMatrixRMaj(1, 1) + CommonOps_FDRM.solve(FMatrixRMaj(a.toEjml().origin), FMatrixRMaj(b.toEjml().origin), res) + return res.wrapMatrix() + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Point): EjmlFloatVector { + val res = FMatrixRMaj(1, 1) + CommonOps_FDRM.solve(FMatrixRMaj(a.toEjml().origin), FMatrixRMaj(b.toEjml().origin), res) + return EjmlFloatVector(res) + } +} + +/** + * [EjmlLinearSpace] implementation based on [CommonOps_DSCC], [DecompositionFactory_DSCC] operations and + * [DMatrixSparseCSC] matrices. + */ +public object EjmlLinearSpaceDSCC : EjmlLinearSpace() { + /** + * The [DoubleField] reference. + */ + public override val elementAlgebra: DoubleField get() = DoubleField + + @Suppress("UNCHECKED_CAST") + public override fun Matrix.toEjml(): EjmlDoubleMatrix = when { + this is EjmlDoubleMatrix<*> && origin is DMatrixSparseCSC -> this as EjmlDoubleMatrix + else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } + } + + @Suppress("UNCHECKED_CAST") + public override fun Point.toEjml(): EjmlDoubleVector = when { + this is EjmlDoubleVector<*> && origin is DMatrixSparseCSC -> this as EjmlDoubleVector + else -> EjmlDoubleVector(DMatrixSparseCSC(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } + }) + } + + public override fun buildMatrix( + rows: Int, + columns: Int, + initializer: DoubleField.(i: Int, j: Int) -> Double, + ): EjmlDoubleMatrix = DMatrixSparseCSC(rows, columns).also { + (0 until rows).forEach { row -> + (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } + } + }.wrapMatrix() + + public override fun buildVector( + size: Int, + initializer: DoubleField.(Int) -> Double, + ): EjmlDoubleVector = EjmlDoubleVector(DMatrixSparseCSC(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } + }) + + private fun T.wrapMatrix() = EjmlDoubleMatrix(this) + private fun T.wrapVector() = EjmlDoubleVector(this) + + public override fun Matrix.unaryMinus(): Matrix = this * elementAlgebra { -one } + + public override fun Matrix.dot(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.mult(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } + + public override fun Matrix.dot(vector: Point): EjmlDoubleVector { + val out = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.mult(toEjml().origin, vector.toEjml().origin, out) + return out.wrapVector() + } + + public override operator fun Matrix.minus(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixSparseCSC(1, 1) + + CommonOps_DSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapMatrix() + } + + public override operator fun Matrix.times(value: Double): EjmlDoubleMatrix { + val res = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.scale(value, toEjml().origin, res) + return res.wrapMatrix() + } + + public override fun Point.unaryMinus(): EjmlDoubleVector { + val res = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.changeSign(toEjml().origin, res) + return res.wrapVector() + } + + public override fun Matrix.plus(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixSparseCSC(1, 1) + + CommonOps_DSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapMatrix() + } + + public override fun Point.plus(other: Point): EjmlDoubleVector { + val out = DMatrixSparseCSC(1, 1) + + CommonOps_DSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapVector() + } + + public override fun Point.minus(other: Point): EjmlDoubleVector { + val out = DMatrixSparseCSC(1, 1) + + CommonOps_DSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapVector() + } + + public override fun Double.times(m: Matrix): EjmlDoubleMatrix = m * this + + public override fun Point.times(value: Double): EjmlDoubleVector { + val res = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.scale(value, toEjml().origin, res) + return res.wrapVector() + } + + public override fun Double.times(v: Point): EjmlDoubleVector = v * this + + @UnstableKMathAPI + public override fun getFeature(structure: Matrix, type: KClass): F? { + structure.getFeature(type)?.let { return it } + val origin = structure.toEjml().origin + + return when (type) { + QRDecompositionFeature::class -> object : QRDecompositionFeature { + private val qr by lazy { + DecompositionFactory_DSCC.qr(FillReducing.NONE).apply { decompose(origin.copy()) } + } + + override val q: Matrix by lazy { + qr.getQ(null, false).wrapMatrix() + OrthogonalFeature + } + + override val r: Matrix by lazy { qr.getR(null, false).wrapMatrix() + UFeature } + } + + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { + override val l: Matrix by lazy { + val cholesky = + DecompositionFactory_DSCC.cholesky().apply { decompose(origin.copy()) } + + (cholesky.getT(null) as DMatrix).wrapMatrix() + LFeature + } + } + + LUDecompositionFeature::class, DeterminantFeature::class, InverseMatrixFeature::class -> object : + LUDecompositionFeature, DeterminantFeature, InverseMatrixFeature { + private val lu by lazy { + DecompositionFactory_DSCC.lu(FillReducing.NONE).apply { decompose(origin.copy()) } + } + + override val l: Matrix by lazy { + lu.getLower(null).wrapMatrix() + LFeature + } + + override val u: Matrix by lazy { + lu.getUpper(null).wrapMatrix() + UFeature + } + + override val inverse: Matrix by lazy { + var a = origin + val inverse = DMatrixRMaj(1, 1) + val solver = LinearSolverFactory_DSCC.lu(FillReducing.NONE) + if (solver.modifiesA()) a = a.copy() + val i = CommonOps_DDRM.identity(a.numRows) + solver.solve(i, inverse) + inverse.wrapMatrix() + } + + override val determinant: Double by lazy { elementAlgebra.number(lu.computeDeterminant().real) } + } + + else -> null + }?.let(type::cast) + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Matrix): EjmlDoubleMatrix { + val res = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.solve(DMatrixSparseCSC(a.toEjml().origin), DMatrixSparseCSC(b.toEjml().origin), res) + return res.wrapMatrix() + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Point): EjmlDoubleVector { + val res = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.solve(DMatrixSparseCSC(a.toEjml().origin), DMatrixSparseCSC(b.toEjml().origin), res) + return EjmlDoubleVector(res) + } +} + +/** + * [EjmlLinearSpace] implementation based on [CommonOps_FSCC], [DecompositionFactory_FSCC] operations and + * [FMatrixSparseCSC] matrices. + */ +public object EjmlLinearSpaceFSCC : EjmlLinearSpace() { + /** + * The [FloatField] reference. + */ + public override val elementAlgebra: FloatField get() = FloatField + + @Suppress("UNCHECKED_CAST") + public override fun Matrix.toEjml(): EjmlFloatMatrix = when { + this is EjmlFloatMatrix<*> && origin is FMatrixSparseCSC -> this as EjmlFloatMatrix + else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } + } + + @Suppress("UNCHECKED_CAST") + public override fun Point.toEjml(): EjmlFloatVector = when { + this is EjmlFloatVector<*> && origin is FMatrixSparseCSC -> this as EjmlFloatVector + else -> EjmlFloatVector(FMatrixSparseCSC(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } + }) + } + + public override fun buildMatrix( + rows: Int, + columns: Int, + initializer: FloatField.(i: Int, j: Int) -> Float, + ): EjmlFloatMatrix = FMatrixSparseCSC(rows, columns).also { + (0 until rows).forEach { row -> + (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } + } + }.wrapMatrix() + + public override fun buildVector( + size: Int, + initializer: FloatField.(Int) -> Float, + ): EjmlFloatVector = EjmlFloatVector(FMatrixSparseCSC(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } + }) + + private fun T.wrapMatrix() = EjmlFloatMatrix(this) + private fun T.wrapVector() = EjmlFloatVector(this) + + public override fun Matrix.unaryMinus(): Matrix = this * elementAlgebra { -one } + + public override fun Matrix.dot(other: Matrix): EjmlFloatMatrix { + val out = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.mult(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } + + public override fun Matrix.dot(vector: Point): EjmlFloatVector { + val out = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.mult(toEjml().origin, vector.toEjml().origin, out) + return out.wrapVector() + } + + public override operator fun Matrix.minus(other: Matrix): EjmlFloatMatrix { + val out = FMatrixSparseCSC(1, 1) + + CommonOps_FSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapMatrix() + } + + public override operator fun Matrix.times(value: Float): EjmlFloatMatrix { + val res = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.scale(value, toEjml().origin, res) + return res.wrapMatrix() + } + + public override fun Point.unaryMinus(): EjmlFloatVector { + val res = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.changeSign(toEjml().origin, res) + return res.wrapVector() + } + + public override fun Matrix.plus(other: Matrix): EjmlFloatMatrix { + val out = FMatrixSparseCSC(1, 1) + + CommonOps_FSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapMatrix() + } + + public override fun Point.plus(other: Point): EjmlFloatVector { + val out = FMatrixSparseCSC(1, 1) + + CommonOps_FSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapVector() + } + + public override fun Point.minus(other: Point): EjmlFloatVector { + val out = FMatrixSparseCSC(1, 1) + + CommonOps_FSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapVector() + } + + public override fun Float.times(m: Matrix): EjmlFloatMatrix = m * this + + public override fun Point.times(value: Float): EjmlFloatVector { + val res = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.scale(value, toEjml().origin, res) + return res.wrapVector() + } + + public override fun Float.times(v: Point): EjmlFloatVector = v * this + + @UnstableKMathAPI + public override fun getFeature(structure: Matrix, type: KClass): F? { + structure.getFeature(type)?.let { return it } + val origin = structure.toEjml().origin + + return when (type) { + QRDecompositionFeature::class -> object : QRDecompositionFeature { + private val qr by lazy { + DecompositionFactory_FSCC.qr(FillReducing.NONE).apply { decompose(origin.copy()) } + } + + override val q: Matrix by lazy { + qr.getQ(null, false).wrapMatrix() + OrthogonalFeature + } + + override val r: Matrix by lazy { qr.getR(null, false).wrapMatrix() + UFeature } + } + + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { + override val l: Matrix by lazy { + val cholesky = + DecompositionFactory_FSCC.cholesky().apply { decompose(origin.copy()) } + + (cholesky.getT(null) as FMatrix).wrapMatrix() + LFeature + } + } + + LUDecompositionFeature::class, DeterminantFeature::class, InverseMatrixFeature::class -> object : + LUDecompositionFeature, DeterminantFeature, InverseMatrixFeature { + private val lu by lazy { + DecompositionFactory_FSCC.lu(FillReducing.NONE).apply { decompose(origin.copy()) } + } + + override val l: Matrix by lazy { + lu.getLower(null).wrapMatrix() + LFeature + } + + override val u: Matrix by lazy { + lu.getUpper(null).wrapMatrix() + UFeature + } + + override val inverse: Matrix by lazy { + var a = origin + val inverse = FMatrixRMaj(1, 1) + val solver = LinearSolverFactory_FSCC.lu(FillReducing.NONE) + if (solver.modifiesA()) a = a.copy() + val i = CommonOps_FDRM.identity(a.numRows) + solver.solve(i, inverse) + inverse.wrapMatrix() + } + + override val determinant: Float by lazy { elementAlgebra.number(lu.computeDeterminant().real) } + } + + else -> null + }?.let(type::cast) + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Matrix): EjmlFloatMatrix { + val res = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.solve(FMatrixSparseCSC(a.toEjml().origin), FMatrixSparseCSC(b.toEjml().origin), res) + return res.wrapMatrix() + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Point): EjmlFloatVector { + val res = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.solve(FMatrixSparseCSC(a.toEjml().origin), FMatrixSparseCSC(b.toEjml().origin), res) + return EjmlFloatVector(res) + } +} + diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt index 9bf76033d..9592bfa6c 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt @@ -18,7 +18,7 @@ internal class EjmlVectorTest { private val randomMatrix: DMatrixRMaj get() { - val d = DMatrixRMaj(random.nextInt(2, 100), 1) + val d = DMatrixRMaj(1, random.nextInt(2, 100)) RandomMatrices_DDRM.fillUniform(d, random.asJavaRandom()) return d } @@ -27,7 +27,7 @@ internal class EjmlVectorTest { fun size() { val m = randomMatrix val w = EjmlDoubleVector(m) - assertEquals(m.numRows, w.size) + assertEquals(m.numCols, w.size) } @Test @@ -43,7 +43,7 @@ internal class EjmlVectorTest { val w = EjmlDoubleVector(m) assertEquals( - m.iterator(true, 0, 0, m.numRows - 1, 0).asSequence().toList(), + m.iterator(true, 0, 0, 0, m.numCols - 1).asSequence().toList(), w.iterator().asSequence().toList() ) } From 15d874fb06c355cfcd3e611b534ae32ba8682a2b Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 16 May 2021 19:53:21 +0300 Subject: [PATCH 351/393] Remove MST.Symbolic Replace it by Symbol LogicAlgebra --- CHANGELOG.md | 1 + .../ExpressionsInterpretersBenchmark.kt | 2 - .../space/kscience/kmath/ast/expressions.kt | 2 +- .../kscience/kmath/ast/kotlingradSupport.kt | 2 +- .../kmath/commons/fit/fitWithAutoDiff.kt | 2 +- .../kotlin/space/kscience/kmath/ast/parser.kt | 3 +- .../kscience/kmath/ast/rendering/features.kt | 8 +- .../TestCompilerConsistencyWithInterpreter.kt | 2 +- .../kmath/ast/TestCompilerOperations.kt | 12 +- .../kmath/ast/TestCompilerVariables.kt | 2 +- .../kotlin/space/kscience/kmath/ast/utils.kt | 2 +- .../space/kscience/kmath/estree/estree.kt | 9 +- .../kmath/estree/internal/ESTreeBuilder.kt | 7 +- .../kmath/wasm/internal/WasmBuilder.kt | 16 +-- .../kotlin/space/kscience/kmath/wasm/wasm.kt | 2 +- .../kscience/kmath/ast/TestExecutionTime.kt | 1 - .../kotlin/space/kscience/kmath/ast/utils.kt | 2 +- .../kscience/kmath/wasm/TestWasmSpecific.kt | 2 +- .../kotlin/space/kscience/kmath/asm/asm.kt | 9 +- .../kmath/asm/internal/mapIntrinsics.kt | 4 +- .../kotlin/space/kscience/kmath/ast/utils.kt | 2 +- .../DerivativeStructureExpression.kt | 1 - .../commons/optimization/CMOptimization.kt | 14 +- .../kmath/commons/optimization/cmFit.kt | 2 +- .../DerivativeStructureExpressionTest.kt | 6 +- .../commons/optimization/OptimizeTest.kt | 2 +- .../complex/ExpressionFieldForComplexTest.kt | 2 +- kmath-core/api/kmath-core.api | 130 +++++++++--------- .../space/kscience/kmath/data/ColumnarData.kt | 2 +- .../kscience/kmath/data/XYColumnarData.kt | 2 +- .../kscience/kmath/data/XYZColumnarData.kt | 2 +- .../expressions/DifferentiableExpression.kt | 3 - .../kscience/kmath/expressions/Expression.kt | 2 - .../FunctionalExpressionAlgebra.kt | 1 - .../space/kscience/kmath/expressions/MST.kt | 19 +-- .../kscience/kmath/expressions/MstAlgebra.kt | 42 ++++-- .../kmath/expressions/SimpleAutoDiff.kt | 1 - .../kmath/{misc => expressions}/Symbol.kt | 7 +- .../kmath/expressions/SymbolIndexer.kt | 1 - .../kscience/kmath/operations/Algebra.kt | 3 +- .../kscience/kmath/operations/LogicAlgebra.kt | 71 ++++++++++ .../kmath/expressions/ExpressionFieldTest.kt | 1 - .../kmath/expressions/InterpretTest.kt | 1 - .../kmath/expressions/SimpleAutoDiffTest.kt | 2 - .../kotlingrad/DifferentiableMstExpression.kt | 10 +- .../kmath/kotlingrad/ScalarsAdapters.kt | 11 +- .../kmath/kotlingrad/AdaptingTests.kt | 12 +- .../optimization/FunctionOptimization.kt | 6 +- .../NoDerivFunctionOptimization.kt | 2 +- .../kmath/optimization/Optimization.kt | 2 +- .../kscience/kmath/optimization/XYFit.kt | 6 +- 51 files changed, 254 insertions(+), 204 deletions(-) rename kmath-core/src/commonMain/kotlin/space/kscience/kmath/{misc => expressions}/Symbol.kt (91%) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a5bde44a..e9a67a0ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ - Rewritten EJML module without ejml-simple - Stability of kmath-ast and kmath-kotilngrad promoted to EXPERIMENTAL. - ColumnarData returns nullable column +- Replaced MST.Symbolic by Symbol. Symbol now inherits MST ### Deprecated diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index 942fba308..15cd14399 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -11,8 +11,6 @@ import kotlinx.benchmark.Scope import kotlinx.benchmark.State import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.Symbol -import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt index 918134e04..d5a82590f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt @@ -6,8 +6,8 @@ package space.kscience.kmath.ast import space.kscience.kmath.expressions.MstField +import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.interpret -import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt index 25f42f5a9..420b23f9f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt @@ -8,8 +8,8 @@ package space.kscience.kmath.ast import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.expressions.derivative import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.expressions.symbol import space.kscience.kmath.kotlingrad.toDiffExpression -import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField /** diff --git a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt index 028985260..5e64235e3 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt @@ -10,7 +10,7 @@ import kotlinx.html.h3 import space.kscience.kmath.commons.optimization.chiSquared import space.kscience.kmath.commons.optimization.minimize import space.kscience.kmath.distributions.NormalDistribution -import space.kscience.kmath.misc.symbol +import space.kscience.kmath.expressions.symbol import space.kscience.kmath.optimization.FunctionOptimization import space.kscience.kmath.optimization.OptimizationResult import space.kscience.kmath.real.DoubleVector diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt index 246625d29..5201fec38 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt @@ -17,6 +17,7 @@ import com.github.h0tk3y.betterParse.lexer.regexToken import com.github.h0tk3y.betterParse.parser.ParseResult import com.github.h0tk3y.betterParse.parser.Parser import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.StringSymbol import space.kscience.kmath.operations.FieldOperations import space.kscience.kmath.operations.GroupOperations import space.kscience.kmath.operations.PowerOperations @@ -42,7 +43,7 @@ public object ArithmeticsEvaluator : Grammar() { private val ws: Token by regexToken("\\s+".toRegex(), ignore = true) private val number: Parser by num use { MST.Numeric(text.toDouble()) } - private val singular: Parser by id use { MST.Symbolic(text) } + private val singular: Parser by id use { StringSymbol(text) } private val unaryFunction: Parser by (id and -lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar) .map { (id, term) -> MST.Unary(id.text, term) } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index ac716f9ff..863825799 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -7,6 +7,7 @@ package space.kscience.kmath.ast.rendering import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import kotlin.reflect.KClass @@ -19,9 +20,8 @@ import kotlin.reflect.KClass @UnstableKMathAPI public object PrintSymbolic : RenderFeature { public override fun render(renderer: FeaturedMathRenderer, node: MST): SymbolSyntax? = - if (node !is MST.Symbolic) null - else - SymbolSyntax(string = node.value) + if (node !is Symbol) null + else SymbolSyntax(string = node.identity) } /** @@ -142,7 +142,7 @@ public class PrettyPrintIntegers(public val types: Set>) : Re @UnstableKMathAPI public class PrettyPrintPi(public val symbols: Set) : RenderFeature { public override fun render(renderer: FeaturedMathRenderer, node: MST): SpecialSymbolSyntax? = - if (node !is MST.Symbolic || node.value !in symbols) + if (node !is Symbol || node.identity !in symbols) null else SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI) diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt index 0d018070c..6209661b3 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt @@ -7,8 +7,8 @@ package space.kscience.kmath.ast import space.kscience.kmath.expressions.MstField import space.kscience.kmath.expressions.MstRing +import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.interpret -import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing import space.kscience.kmath.operations.bindSymbol diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt index 7d2af31c2..073a03f14 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt @@ -6,8 +6,8 @@ package space.kscience.kmath.ast import space.kscience.kmath.expressions.MstExtendedField +import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke @@ -17,31 +17,31 @@ import kotlin.test.assertEquals internal class TestCompilerOperations { @Test fun testUnaryPlus() = runCompilerTest { - val expr = MstExtendedField { +bindSymbol(x) }.compileToExpression(DoubleField) + val expr = MstExtendedField { +x }.compileToExpression(DoubleField) assertEquals(2.0, expr(x to 2.0)) } @Test fun testUnaryMinus() = runCompilerTest { - val expr = MstExtendedField { -bindSymbol(x) }.compileToExpression(DoubleField) + val expr = MstExtendedField { -x }.compileToExpression(DoubleField) assertEquals(-2.0, expr(x to 2.0)) } @Test fun testAdd() = runCompilerTest { - val expr = MstExtendedField { bindSymbol(x) + bindSymbol(x) }.compileToExpression(DoubleField) + val expr = MstExtendedField { x + x }.compileToExpression(DoubleField) assertEquals(4.0, expr(x to 2.0)) } @Test fun testSine() = runCompilerTest { - val expr = MstExtendedField { sin(bindSymbol(x)) }.compileToExpression(DoubleField) + val expr = MstExtendedField { sin(x) }.compileToExpression(DoubleField) assertEquals(0.0, expr(x to 0.0)) } @Test fun testCosine() = runCompilerTest { - val expr = MstExtendedField { cos(bindSymbol(x)) }.compileToExpression(DoubleField) + val expr = MstExtendedField { cos(x) }.compileToExpression(DoubleField) assertEquals(1.0, expr(x to 0.0)) } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt index ecf8ed367..dcc15b311 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt @@ -6,8 +6,8 @@ package space.kscience.kmath.ast import space.kscience.kmath.expressions.MstRing +import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.IntRing import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt index abeaed0f8..ec7436188 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.ast import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt index 40468f5ab..0c15e994c 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt @@ -9,22 +9,23 @@ import space.kscience.kmath.estree.internal.ESTreeBuilder import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MST.* +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.invoke import space.kscience.kmath.internal.estree.BaseExpression -import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.NumericAlgebra +import space.kscience.kmath.operations.bindSymbolOrNull @PublishedApi internal fun MST.compileWith(algebra: Algebra): Expression { fun ESTreeBuilder.visit(node: MST): BaseExpression = when (node) { - is Symbolic -> { - val symbol = algebra.bindSymbolOrNull(node.value) + is Symbol -> { + val symbol = algebra.bindSymbolOrNull(node) if (symbol != null) constant(symbol) else - variable(node.value) + variable(node.identity) } is Numeric -> constant(node.value) diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt index ac20484a4..4907d8225 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -6,14 +6,9 @@ package space.kscience.kmath.estree.internal import space.kscience.kmath.expressions.Expression +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.internal.astring.generate import space.kscience.kmath.internal.estree.* -import space.kscience.kmath.internal.estree.BaseExpression -import space.kscience.kmath.internal.estree.BlockStatement -import space.kscience.kmath.internal.estree.Program -import space.kscience.kmath.internal.estree.VariableDeclaration -import space.kscience.kmath.internal.estree.VariableDeclarator -import space.kscience.kmath.misc.Symbol internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExpression) { private class GeneratedExpression(val executable: dynamic, val constants: Array) : Expression { diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt index 8fd3c9fb9..95ace1bad 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -8,9 +8,9 @@ package space.kscience.kmath.wasm.internal import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MST.* +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.internal.binaryen.* import space.kscience.kmath.internal.webassembly.Instance -import space.kscience.kmath.misc.StringSymbol import space.kscience.kmath.operations.* import space.kscience.kmath.internal.binaryen.Module as BinaryenModule import space.kscience.kmath.internal.webassembly.Module as WasmModule @@ -23,20 +23,20 @@ internal sealed class WasmBuilder( val algebra: Algebra, val target: MST, ) where T : Number { - val keys: MutableList = mutableListOf() + val keys: MutableList = mutableListOf() lateinit var ctx: BinaryenModule - open fun visitSymbolic(mst: Symbolic): ExpressionRef { + open fun visitSymbolic(mst: Symbol): ExpressionRef { try { - algebra.bindSymbol(mst.value) + algebra.bindSymbol(mst) } catch (ignored: Throwable) { null }?.let { return visitNumeric(Numeric(it)) } - var idx = keys.indexOf(mst.value) + var idx = keys.indexOf(mst) if (idx == -1) { - keys += mst.value + keys += mst idx = keys.lastIndex } @@ -54,7 +54,7 @@ internal sealed class WasmBuilder( open fun createModule(): BinaryenModule = js("new \$module\$binaryen.Module()") fun visit(mst: MST): ExpressionRef = when (mst) { - is Symbolic -> visitSymbolic(mst) + is Symbol -> visitSymbolic(mst) is Numeric -> visitNumeric(mst) is Unary -> when { @@ -96,7 +96,7 @@ internal sealed class WasmBuilder( }) val i = Instance(c, js("{}") as Any) - val symbols = keys.map(::StringSymbol) + val symbols = keys keys.clear() Expression { args -> diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt index 394a0567e..6ea8f26c1 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt @@ -8,8 +8,8 @@ package space.kscience.kmath.wasm import space.kscience.kmath.estree.compileWith import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt index 01746ddb6..6cb378182 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt @@ -6,7 +6,6 @@ package space.kscience.kmath.ast import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.bindSymbol diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt index 6b5b1b83d..93b7e9449 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.ast import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing import space.kscience.kmath.estree.compile as estreeCompile diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt index dd5452d04..abdf865c7 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.wasm import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol +import space.kscience.kmath.expressions.symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing import space.kscience.kmath.operations.bindSymbol diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt index dbce893d1..4147324ee 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt @@ -10,10 +10,11 @@ import space.kscience.kmath.asm.internal.buildName import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.MST.* +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.NumericAlgebra +import space.kscience.kmath.operations.bindSymbolOrNull /** * Compiles given MST to an Expression using AST compiler. @@ -26,13 +27,13 @@ import space.kscience.kmath.operations.NumericAlgebra @PublishedApi internal fun MST.compileWith(type: Class, algebra: Algebra): Expression { fun AsmBuilder.visit(node: MST): Unit = when (node) { - is Symbolic -> { - val symbol = algebra.bindSymbolOrNull(node.value) + is Symbol -> { + val symbol = algebra.bindSymbolOrNull(node) if (symbol != null) loadObjectConstant(symbol as Any) else - loadVariable(node.value) + loadVariable(node.identity) } is Numeric -> loadNumberConstant(node.value) diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt index dc8f19fb6..8f4daecf9 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt @@ -7,8 +7,8 @@ package space.kscience.kmath.asm.internal -import space.kscience.kmath.misc.StringSymbol -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.expressions.StringSymbol +import space.kscience.kmath.expressions.Symbol /** * Gets value with given [key] or throws [NoSuchElementException] whenever it is not present. diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt index 607c5fdd6..d3b554efd 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.ast import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing import space.kscience.kmath.asm.compile as asmCompile diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 736685789..89e216601 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -7,7 +7,6 @@ package space.kscience.kmath.commons.expressions import org.apache.commons.math3.analysis.differentiation.DerivativeStructure import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.NumbersAddOperations diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt index cfb8c39be..bca00de46 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt @@ -14,13 +14,17 @@ import org.apache.commons.math3.optim.nonlinear.scalar.gradient.NonLinearConjuga import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.AbstractSimplex import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer -import space.kscience.kmath.expressions.DifferentiableExpression -import space.kscience.kmath.expressions.Expression -import space.kscience.kmath.expressions.SymbolIndexer -import space.kscience.kmath.expressions.derivative -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.expressions.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.optimization.* +import kotlin.collections.HashMap +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.set +import kotlin.collections.setOf +import kotlin.collections.toList +import kotlin.collections.toMap +import kotlin.collections.toTypedArray import kotlin.reflect.KClass public operator fun PointValuePair.component1(): DoubleArray = point diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt index 13b5c73f4..a5a913623 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt @@ -9,7 +9,7 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure import space.kscience.kmath.commons.expressions.DerivativeStructureField import space.kscience.kmath.expressions.DifferentiableExpression import space.kscience.kmath.expressions.Expression -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.optimization.FunctionOptimization import space.kscience.kmath.optimization.OptimizationResult import space.kscience.kmath.optimization.noDerivOptimizeWith diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt index 879cd75b1..966675062 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt @@ -5,11 +5,7 @@ package space.kscience.kmath.commons.expressions -import space.kscience.kmath.expressions.binding -import space.kscience.kmath.expressions.derivative -import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.Symbol -import space.kscience.kmath.misc.symbol +import space.kscience.kmath.expressions.* import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.test.Test diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt index 716cd1b0f..15c9120ec 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.commons.optimization import kotlinx.coroutines.runBlocking import space.kscience.kmath.commons.expressions.DerivativeStructureExpression import space.kscience.kmath.distributions.NormalDistribution -import space.kscience.kmath.misc.symbol +import space.kscience.kmath.expressions.symbol import space.kscience.kmath.optimization.FunctionOptimization import space.kscience.kmath.stat.RandomGenerator import kotlin.math.pow diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt index e023fcb81..4279471d4 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.complex import space.kscience.kmath.expressions.FunctionalExpressionField import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.symbol +import space.kscience.kmath.expressions.symbol import space.kscience.kmath.operations.bindSymbol import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 7b09b668b..ead4b96b5 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -21,7 +21,7 @@ public class space/kscience/kmath/expressions/AutoDiffValue { public final class space/kscience/kmath/expressions/DerivationResult { public fun (Ljava/lang/Object;Ljava/util/Map;Lspace/kscience/kmath/operations/Field;)V - public final fun derivative (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; + public final fun derivative (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; public final fun div ()Ljava/lang/Object; public final fun getContext ()Lspace/kscience/kmath/operations/Field; public final fun getValue ()Ljava/lang/Object; @@ -34,7 +34,7 @@ public abstract interface class space/kscience/kmath/expressions/DifferentiableE public final class space/kscience/kmath/expressions/DifferentiableExpressionKt { public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression; public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; - public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;[Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression; + public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;[Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression; } public abstract interface class space/kscience/kmath/expressions/Expression { @@ -55,7 +55,7 @@ public final class space/kscience/kmath/expressions/ExpressionKt { public abstract class space/kscience/kmath/expressions/FirstDerivativeExpression : space/kscience/kmath/expressions/DifferentiableExpression { public fun ()V public final fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; - public abstract fun derivativeOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression; + public abstract fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression; } public abstract class space/kscience/kmath/expressions/FunctionalExpressionAlgebra : space/kscience/kmath/expressions/ExpressionAlgebra { @@ -146,7 +146,7 @@ public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/k public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } -public abstract class space/kscience/kmath/expressions/MST { +public abstract interface class space/kscience/kmath/expressions/MST { } public final class space/kscience/kmath/expressions/MST$Binary : space/kscience/kmath/expressions/MST { @@ -175,17 +175,6 @@ public final class space/kscience/kmath/expressions/MST$Numeric : space/kscience public fun toString ()Ljava/lang/String; } -public final class space/kscience/kmath/expressions/MST$Symbolic : space/kscience/kmath/expressions/MST { - public fun (Ljava/lang/String;)V - public final fun component1 ()Ljava/lang/String; - public final fun copy (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; - public static synthetic fun copy$default (Lspace/kscience/kmath/expressions/MST$Symbolic;Ljava/lang/String;ILjava/lang/Object;)Lspace/kscience/kmath/expressions/MST$Symbolic; - public fun equals (Ljava/lang/Object;)Z - public final fun getValue ()Ljava/lang/String; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - public final class space/kscience/kmath/expressions/MST$Unary : space/kscience/kmath/expressions/MST { public fun (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)V public final fun component1 ()Ljava/lang/String; @@ -206,18 +195,6 @@ public final class space/kscience/kmath/expressions/MSTKt { public static final fun toExpression (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/operations/Algebra;)Lspace/kscience/kmath/expressions/Expression; } -public final class space/kscience/kmath/expressions/MstAlgebra : space/kscience/kmath/operations/NumericAlgebra { - public static final field INSTANCE Lspace/kscience/kmath/expressions/MstAlgebra; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; - public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; -} - public final class space/kscience/kmath/expressions/MstExtendedField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumericAlgebra { public static final field INSTANCE Lspace/kscience/kmath/expressions/MstExtendedField; public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; @@ -236,7 +213,7 @@ public final class space/kscience/kmath/expressions/MstExtendedField : space/ksc public fun atanh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol; public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; public fun cos (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; @@ -284,7 +261,7 @@ public final class space/kscience/kmath/expressions/MstField : space/kscience/km public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; public synthetic fun getOne ()Ljava/lang/Object; @@ -312,7 +289,7 @@ public final class space/kscience/kmath/expressions/MstGroup : space/kscience/km public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol; public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric; public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -328,13 +305,25 @@ public final class space/kscience/kmath/expressions/MstGroup : space/kscience/km public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; } +public final class space/kscience/kmath/expressions/MstNumericAlgebra : space/kscience/kmath/operations/NumericAlgebra { + public static final field INSTANCE Lspace/kscience/kmath/expressions/MstNumericAlgebra; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; +} + public final class space/kscience/kmath/expressions/MstRing : space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/Ring, space/kscience/kmath/operations/ScaleOperations { public static final field INSTANCE Lspace/kscience/kmath/expressions/MstRing; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/expressions/MST$Numeric; public synthetic fun getZero ()Ljava/lang/Object; @@ -356,7 +345,7 @@ public final class space/kscience/kmath/expressions/MstRing : space/kscience/kma public final class space/kscience/kmath/expressions/SimpleAutoDiffExpression : space/kscience/kmath/expressions/FirstDerivativeExpression { public fun (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)V - public fun derivativeOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression; + public fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression; public final fun getField ()Lspace/kscience/kmath/operations/Field; public final fun getFunction ()Lkotlin/jvm/functions/Function1; public fun invoke (Ljava/util/Map;)Ljava/lang/Object; @@ -445,7 +434,7 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt { public static final fun cos (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public static final fun cosh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public static final fun exp (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; - public static final fun grad (Lspace/kscience/kmath/expressions/DerivationResult;[Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer; + public static final fun grad (Lspace/kscience/kmath/expressions/DerivationResult;[Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer; public static final fun ln (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; public static final fun pow (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;D)Lspace/kscience/kmath/expressions/AutoDiffValue; public static final fun pow (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;I)Lspace/kscience/kmath/expressions/AutoDiffValue; @@ -461,9 +450,42 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt { public static final fun tanh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; } +public final class space/kscience/kmath/expressions/StringSymbol : space/kscience/kmath/expressions/Symbol { + public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/expressions/StringSymbol; + public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z + public fun getIdentity ()Ljava/lang/String; + public fun hashCode ()I + public static fun hashCode-impl (Ljava/lang/String;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Ljava/lang/String; +} + +public abstract interface class space/kscience/kmath/expressions/Symbol : space/kscience/kmath/expressions/MST { + public static final field Companion Lspace/kscience/kmath/expressions/Symbol$Companion; + public abstract fun getIdentity ()Ljava/lang/String; +} + +public final class space/kscience/kmath/expressions/Symbol$Companion { + public final fun getX-uKgCeAI ()Ljava/lang/String; + public final fun getY-uKgCeAI ()Ljava/lang/String; + public final fun getZ-uKgCeAI ()Ljava/lang/String; +} + public final class space/kscience/kmath/expressions/SymbolIndexerKt { } +public final class space/kscience/kmath/expressions/SymbolKt { + public static final fun get (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object; + public static final fun get (Ljava/util/Map;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public static final fun getSymbol ()Lkotlin/properties/ReadOnlyProperty; + public static final fun set (Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)V + public static final fun set (Ljava/util/Map;Lspace/kscience/kmath/expressions/Symbol;Ljava/lang/Object;)V +} + public final class space/kscience/kmath/linear/BufferedLinearSpace : space/kscience/kmath/linear/LinearSpace { public fun (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V public fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D; @@ -677,39 +699,6 @@ public final class space/kscience/kmath/misc/CumulativeKt { public abstract interface annotation class space/kscience/kmath/misc/PerformancePitfall : java/lang/annotation/Annotation { } -public final class space/kscience/kmath/misc/StringSymbol : space/kscience/kmath/misc/Symbol { - public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/misc/StringSymbol; - public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z - public fun getIdentity ()Ljava/lang/String; - public fun hashCode ()I - public static fun hashCode-impl (Ljava/lang/String;)I - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Ljava/lang/String; -} - -public abstract interface class space/kscience/kmath/misc/Symbol { - public static final field Companion Lspace/kscience/kmath/misc/Symbol$Companion; - public abstract fun getIdentity ()Ljava/lang/String; -} - -public final class space/kscience/kmath/misc/Symbol$Companion { - public final fun getX-tWtZOCg ()Ljava/lang/String; - public final fun getY-tWtZOCg ()Ljava/lang/String; - public final fun getZ-tWtZOCg ()Ljava/lang/String; -} - -public final class space/kscience/kmath/misc/SymbolKt { - public static final fun get (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object; - public static final fun get (Ljava/util/Map;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; - public static final fun getSymbol ()Lkotlin/properties/ReadOnlyProperty; - public static final fun set (Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)V - public static final fun set (Ljava/util/Map;Lspace/kscience/kmath/misc/Symbol;Ljava/lang/Object;)V -} - public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation { } @@ -1028,8 +1017,8 @@ public final class space/kscience/kmath/operations/AlgebraExtensionsKt { } public final class space/kscience/kmath/operations/AlgebraKt { - public static final fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; - public static final fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object; + public static final fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public static final fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; public static final fun invoke (Lspace/kscience/kmath/operations/Algebra;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } @@ -1414,6 +1403,11 @@ public final class space/kscience/kmath/operations/JBigIntegerField : space/ksci public abstract interface annotation class space/kscience/kmath/operations/KMathContext : java/lang/annotation/Annotation { } +public final class space/kscience/kmath/operations/LogicAlgebra$Companion { + public final fun getFALSE ()Lspace/kscience/kmath/expressions/Symbol; + public final fun getTRUE ()Lspace/kscience/kmath/expressions/Symbol; +} + public final class space/kscience/kmath/operations/LongRing : space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring { public static final field INSTANCE Lspace/kscience/kmath/operations/LongRing; public fun add (JJ)Ljava/lang/Long; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt index f5193ecd2..88c14d311 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.data +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.structures.Buffer diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt index bbd679ce9..08bfd3ca3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.data +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.structures.Buffer diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt index 3972429a5..39a6b858c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.data -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt index dbc1431b3..33d72afad 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt @@ -5,9 +5,6 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.misc.StringSymbol -import space.kscience.kmath.misc.Symbol - /** * Represents expression which structure can be differentiated. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt index a9ab8648f..84e66918f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt @@ -5,8 +5,6 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.misc.StringSymbol -import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra import kotlin.jvm.JvmName import kotlin.properties.ReadOnlyProperty diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index 994d52a73..951ec9474 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.misc.StringSymbol import space.kscience.kmath.operations.* /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt index 67881d9af..0e046ae5c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt @@ -5,30 +5,23 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.misc.StringSymbol -import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.NumericAlgebra +import space.kscience.kmath.operations.bindSymbol /** * A Mathematical Syntax Tree (MST) node for mathematical expressions. * * @author Alexander Nozik */ -public sealed class MST { - /** - * A node containing raw string. - * - * @property value the value of this node. - */ - public data class Symbolic(val value: String) : MST() +public sealed interface MST { /** * A node containing a numeric value or scalar. * * @property value the value of this number. */ - public data class Numeric(val value: Number) : MST() + public data class Numeric(val value: Number) : MST /** * A node containing an unary operation. @@ -36,7 +29,7 @@ public sealed class MST { * @property operation the identifier of operation. * @property value the argument of this operation. */ - public data class Unary(val operation: String, val value: MST) : MST() + public data class Unary(val operation: String, val value: MST) : MST /** * A node containing binary operation. @@ -45,7 +38,7 @@ public sealed class MST { * @property left the left operand. * @property right the right operand. */ - public data class Binary(val operation: String, val left: MST, val right: MST) : MST() + public data class Binary(val operation: String, val left: MST, val right: MST) : MST } // TODO add a function with named arguments @@ -62,7 +55,7 @@ public fun Algebra.evaluate(node: MST): T = when (node) { is MST.Numeric -> (this as? NumericAlgebra)?.number(node.value) ?: error("Numeric nodes are not supported by $this") - is MST.Symbolic -> bindSymbol(node.value) + is Symbol -> bindSymbol(node) is MST.Unary -> when { this is NumericAlgebra && node.value is MST.Numeric -> unaryOperationFunction(node.operation)(number(node.value.value)) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt index 53124b777..fb2e38449 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt @@ -11,10 +11,10 @@ import space.kscience.kmath.operations.* /** * [Algebra] over [MST] nodes. */ -public object MstAlgebra : NumericAlgebra { +public object MstNumericAlgebra : NumericAlgebra { public override fun number(value: Number): MST.Numeric = MST.Numeric(value) - public override fun bindSymbolOrNull(value: String): MST.Symbolic = MST.Symbolic(value) - override fun bindSymbol(value: String): MST.Symbolic = bindSymbolOrNull(value) + public override fun bindSymbolOrNull(value: String): Symbol = StringSymbol(value) + override fun bindSymbol(value: String): Symbol = bindSymbolOrNull(value) public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = { arg -> MST.Unary(operation, arg) } @@ -29,8 +29,8 @@ public object MstAlgebra : NumericAlgebra { public object MstGroup : Group, NumericAlgebra, ScaleOperations { public override val zero: MST.Numeric = number(0.0) - public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) - public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value) + public override fun number(value: Number): MST.Numeric = MstNumericAlgebra.number(value) + public override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value) public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(GroupOperations.PLUS_OPERATION)(a, b) public override operator fun MST.unaryPlus(): MST.Unary = unaryOperationFunction(GroupOperations.PLUS_OPERATION)(this) @@ -45,10 +45,10 @@ public object MstGroup : Group, NumericAlgebra, ScaleOperations { binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(value)) public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = - MstAlgebra.binaryOperationFunction(operation) + MstNumericAlgebra.binaryOperationFunction(operation) public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = - MstAlgebra.unaryOperationFunction(operation) + MstNumericAlgebra.unaryOperationFunction(operation) } /** @@ -61,7 +61,7 @@ public object MstRing : Ring, NumbersAddOperations, ScaleOperations, NumbersAddOperations, ScaleOperations MST.Unary = - MstAlgebra.unaryOperationFunction(operation) + MstNumericAlgebra.unaryOperationFunction(operation) } /** @@ -90,7 +90,7 @@ public object MstField : Field, NumbersAddOperations, ScaleOperations< public override inline val zero: MST.Numeric get() = MstRing.zero public override inline val one: MST.Numeric get() = MstRing.one - public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value) + public override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value) public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b) @@ -120,7 +120,7 @@ public object MstExtendedField : ExtendedField, NumericAlgebra { public override inline val zero: MST.Numeric get() = MstField.zero public override inline val one: MST.Numeric get() = MstField.one - public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value) + public override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value) public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg) public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg) @@ -158,3 +158,23 @@ public object MstExtendedField : ExtendedField, NumericAlgebra { public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = MstField.unaryOperationFunction(operation) } + +/** + * Logic algebra for [MST] + */ +@UnstableKMathAPI +public object MstLogicAlgebra : LogicAlgebra { + public override fun bindSymbolOrNull(value: String): MST = super.bindSymbolOrNull(value) ?: StringSymbol(value) + + override fun const(boolean: Boolean): Symbol = if (boolean) { + LogicAlgebra.TRUE + } else { + LogicAlgebra.FALSE + } + + override fun MST.not(): MST = MST.Unary(Boolean::not.name, this) + + override fun MST.and(other: MST): MST = MST.Binary(Boolean::and.name, this, other) + + override fun MST.or(other: MST): MST = MST.Binary(Boolean::or.name, this, other) +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt index 09a5faa12..254d60b3d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -6,7 +6,6 @@ package space.kscience.kmath.expressions import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import space.kscience.kmath.structures.asBuffer diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt similarity index 91% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt rename to kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt index b9fb6879a..10a9ca5a1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Symbol.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt @@ -3,15 +3,16 @@ * 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.misc +package space.kscience.kmath.expressions import kotlin.jvm.JvmInline import kotlin.properties.ReadOnlyProperty /** - * A marker interface for a symbol. A symbol mus have an identity + * A marker interface for a symbol. A symbol must have an identity. + * Ic */ -public interface Symbol { +public interface Symbol: MST { /** * Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt index 738156975..06634704c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt @@ -6,7 +6,6 @@ package space.kscience.kmath.expressions import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.structures.BufferFactory diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 9a52d17f4..09bda6508 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -5,8 +5,7 @@ package space.kscience.kmath.operations -import space.kscience.kmath.misc.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.expressions.Symbol /** * Stub for DSL the [Algebra] is. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt new file mode 100644 index 000000000..2bef3f407 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt @@ -0,0 +1,71 @@ +/* + * 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.operations + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.misc.UnstableKMathAPI + +/** + * An algebra for generic boolean logic + */ +@UnstableKMathAPI +public interface LogicAlgebra : Algebra { + + /** + * Represent constant [Boolean] as [T] + */ + public fun const(boolean: Boolean): T + + override fun bindSymbolOrNull(value: String): T? = value.lowercase().toBooleanStrictOrNull()?.let(::const) + + override fun unaryOperation(operation: String, arg: T): T = when (operation) { + Boolean::not.name -> arg.not() + else -> super.unaryOperation(operation, arg) + } + + override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) { + Boolean::and.name -> left.and(right) + Boolean::or.name -> left.or(right) + else -> super.binaryOperation(operation, left, right) + } + + /** + * Logic 'not' + */ + public operator fun T.not(): T + + /** + * Logic 'and' + */ + public infix fun T.and(other: T): T + + /** + * Logic 'or' + */ + public infix fun T.or(other: T): T + + public companion object { + public val TRUE: Symbol by symbol + public val FALSE: Symbol by symbol + } +} + +/** + * An implementation of [LogicAlgebra] for primitive booleans + */ +@UnstableKMathAPI +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +public object BooleanAlgebra : LogicAlgebra { + + override fun const(boolean: Boolean): Boolean = boolean + + override fun Boolean.not(): Boolean = !this + + override fun Boolean.and(other: Boolean): Boolean = this && other + + override fun Boolean.or(other: Boolean): Boolean = this || other +} \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt index cf3a565bc..ace67db06 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke import kotlin.test.Test diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt index 980819364..0df9fe5cf 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.misc.Symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt index ab509650a..c6852cbbf 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -5,8 +5,6 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.misc.Symbol -import space.kscience.kmath.misc.symbol import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.structures.Buffer diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt index 8c6745c79..59d481d02 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt @@ -7,11 +7,7 @@ package space.kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.api.SFun import edu.umontreal.kotlingrad.api.SVar -import space.kscience.kmath.expressions.DifferentiableExpression -import space.kscience.kmath.expressions.MST -import space.kscience.kmath.expressions.MstAlgebra -import space.kscience.kmath.expressions.interpret -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.expressions.* import space.kscience.kmath.operations.NumericAlgebra /** @@ -35,8 +31,8 @@ public class DifferentiableMstExpression>( DifferentiableMstExpression( algebra, symbols.map(Symbol::identity) - .map(MstAlgebra::bindSymbol) - .map>>(MST.Symbolic::toSVar) + .map(MstNumericAlgebra::bindSymbol) + .map>>(Symbol::toSVar) .fold(mst.toSFun(), SFun>::d) .toMst(), ) diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt index bee2c9e3e..8e3c54035 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt @@ -7,9 +7,10 @@ package space.kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.api.* import space.kscience.kmath.expressions.MST -import space.kscience.kmath.expressions.MstAlgebra import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.MstExtendedField.unaryMinus +import space.kscience.kmath.expressions.MstNumericAlgebra +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.operations.* /** @@ -18,7 +19,7 @@ import space.kscience.kmath.operations.* * @receiver The variable. * @returnAa node. */ -public fun > SVar.toMst(): MST.Symbolic = MstAlgebra.bindSymbol(name) +public fun > SVar.toMst(): Symbol = MstNumericAlgebra.bindSymbol(name) /** * Maps [SVar] to [MST.Numeric] directly. @@ -26,7 +27,7 @@ public fun > SVar.toMst(): MST.Symbolic = MstAlgebra.bindSymbol(n * @receiver The constant. * @return A node. */ -public fun > SConst.toMst(): MST.Numeric = MstAlgebra.number(doubleValue) +public fun > SConst.toMst(): MST.Numeric = MstNumericAlgebra.number(doubleValue) /** * Maps [SFun] objects to [MST]. Some unsupported operations like [Derivative] are bound and converted then. @@ -85,7 +86,7 @@ public fun > MST.Numeric.toSConst(): SConst = SConst(value) * @receiver The node. * @return A new variable. */ -internal fun > MST.Symbolic.toSVar(): SVar = SVar(value) +internal fun > Symbol.toSVar(): SVar = SVar(identity) /** * Maps [MST] objects to [SFun]. Unsupported operations throw [IllegalStateException]. @@ -102,7 +103,7 @@ internal fun > MST.Symbolic.toSVar(): SVar = SVar(value) */ public fun > MST.toSFun(): SFun = when (this) { is MST.Numeric -> toSConst() - is MST.Symbolic -> toSVar() + is Symbol -> toSVar() is MST.Unary -> when (operation) { GroupOperations.PLUS_OPERATION -> +value.toSFun() diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index 85c964c58..57fe2411c 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -8,9 +8,9 @@ package space.kscience.kmath.kotlingrad import edu.umontreal.kotlingrad.api.* import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.ast.parseMath -import space.kscience.kmath.expressions.MstAlgebra +import space.kscience.kmath.expressions.MstNumericAlgebra +import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.misc.Symbol.Companion.x import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals @@ -20,7 +20,7 @@ import kotlin.test.fail internal class AdaptingTests { @Test fun symbol() { - val c1 = MstAlgebra.bindSymbol(x.identity) + val c1 = MstNumericAlgebra.bindSymbol(x.identity) assertEquals(x.identity, c1.toSVar>().name) val c2 = "kitten".parseMath().toSFun>() if (c2 is SVar) assertTrue(c2.name == "kitten") else fail() @@ -28,7 +28,7 @@ internal class AdaptingTests { @Test fun number() { - val c1 = MstAlgebra.number(12354324) + val c1 = MstNumericAlgebra.number(12354324) assertTrue(c1.toSConst().doubleValue == 12354324.0) val c2 = "0.234".parseMath().toSFun>() if (c2 is SConst) assertTrue(c2.doubleValue == 0.234) else fail() @@ -46,7 +46,7 @@ internal class AdaptingTests { @Test fun simpleFunctionDerivative() { - val xSVar = MstAlgebra.bindSymbol(x.identity).toSVar>() + val xSVar = MstNumericAlgebra.bindSymbol(x.identity).toSVar>() val quadratic = "x^2-4*x-44".parseMath().toSFun>() val actualDerivative = quadratic.d(xSVar).toMst().compileToExpression(DoubleField) val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField) @@ -55,7 +55,7 @@ internal class AdaptingTests { @Test fun moreComplexDerivative() { - val xSVar = MstAlgebra.bindSymbol(x.identity).toSVar>() + val xSVar = MstNumericAlgebra.bindSymbol(x.identity).toSVar>() val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun>() val actualDerivative = composition.d(xSVar).toMst().compileToExpression(DoubleField) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt index 38f3038c2..4cf5aea84 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt @@ -5,11 +5,7 @@ package space.kscience.kmath.optimization -import space.kscience.kmath.expressions.AutoDiffProcessor -import space.kscience.kmath.expressions.DifferentiableExpression -import space.kscience.kmath.expressions.Expression -import space.kscience.kmath.expressions.ExpressionAlgebra -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.expressions.* import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.indices diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt index 67a21bf2a..0f2167549 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/NoDerivFunctionOptimization.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.optimization import space.kscience.kmath.expressions.Expression -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.indices import kotlin.math.pow diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt index 3b9868815..4a1676412 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimization.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.optimization -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.expressions.Symbol public interface OptimizationFeature diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt index f5cfa05e6..633e9ae0e 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt @@ -6,11 +6,7 @@ package space.kscience.kmath.optimization import space.kscience.kmath.data.ColumnarData -import space.kscience.kmath.expressions.AutoDiffProcessor -import space.kscience.kmath.expressions.DifferentiableExpression -import space.kscience.kmath.expressions.Expression -import space.kscience.kmath.expressions.ExpressionAlgebra -import space.kscience.kmath.misc.Symbol +import space.kscience.kmath.expressions.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.Field From 516444d1bc25cd810e685a00a7098f1ff38d97d6 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 16 May 2021 20:51:46 +0300 Subject: [PATCH 352/393] Fix and test --- .../space/kscience/kmath/expressions/MST.kt | 6 +++--- .../kscience/kmath/operations/Algebra.kt | 2 +- .../kscience/kmath/operations/LogicAlgebra.kt | 6 ++++++ .../kmath/expressions/ExpressionFieldTest.kt | 3 +-- .../kmath/expressions/InterpretTest.kt | 20 ++++++++++++++++--- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt index 0e046ae5c..7533024a1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt @@ -76,7 +76,7 @@ public fun Algebra.evaluate(node: MST): T = when (node) { } } -internal class InnerAlgebra(val algebra: Algebra, val arguments: Map) : NumericAlgebra { +internal class InnerAlgebra(val algebra: Algebra, val arguments: Map) : NumericAlgebra { override fun bindSymbolOrNull(value: String): T? = algebra.bindSymbolOrNull(value) ?: arguments[StringSymbol(value)] override fun unaryOperation(operation: String, arg: T): T = @@ -101,7 +101,7 @@ internal class InnerAlgebra(val algebra: Algebra, val arguments: Map /** * Interprets the [MST] node with this [Algebra] and optional [arguments] */ -public fun MST.interpret(algebra: Algebra, arguments: Map): T = +public fun MST.interpret(algebra: Algebra, arguments: Map): T = InnerAlgebra(algebra, arguments).evaluate(this) /** @@ -111,7 +111,7 @@ public fun MST.interpret(algebra: Algebra, arguments: Map MST.interpret(algebra: Algebra, vararg arguments: Pair): T = +public fun MST.interpret(algebra: Algebra, vararg arguments: Pair): T = interpret(algebra, mapOf(*arguments)) /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 09bda6508..aa22b8c19 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -84,7 +84,7 @@ public interface Algebra { * @return an operation. */ public fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = - error("Binary operation $operation not defined in $this") + error("Binary operation '$operation; not defined in $this") /** * Dynamically invokes a binary operation with the certain name. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt index 2bef3f407..406967897 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt @@ -27,12 +27,18 @@ public interface LogicAlgebra : Algebra { else -> super.unaryOperation(operation, arg) } + override fun unaryOperationFunction(operation: String): (arg: T) -> T = { unaryOperation(operation, it) } + override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) { Boolean::and.name -> left.and(right) Boolean::or.name -> left.or(right) else -> super.binaryOperation(operation, left, right) } + override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = { l, r -> + binaryOperation(operation, l, r) + } + /** * Logic 'not' */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt index ace67db06..4d1b00b3d 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt @@ -6,7 +6,6 @@ package space.kscience.kmath.expressions import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFails @@ -16,7 +15,7 @@ class ExpressionFieldTest { @Test fun testExpression() { - val expression = FunctionalExpressionField(DoubleField).invoke { + val expression = with(FunctionalExpressionField(DoubleField)) { val x by binding() x * x + 2 * x + one } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt index 0df9fe5cf..156334b2e 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt @@ -5,18 +5,32 @@ package space.kscience.kmath.expressions +import space.kscience.kmath.expressions.Symbol.Companion.x +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.BooleanAlgebra import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test +import kotlin.test.assertEquals + internal class InterpretTest { @Test fun interpretation() { val expr = MstField { - val x = bindSymbol(Symbol.x) x * 2.0 + number(2.0) / x - 16.0 }.toExpression(DoubleField) - expr(Symbol.x to 2.2) + assertEquals(-10.69, expr(x to 2.2), 0.02) + } + + @Test + @UnstableKMathAPI + fun booleanAlgebra() { + val expr = MstLogicAlgebra { + x and const(true) + }.toExpression(BooleanAlgebra) + + assertEquals(true, expr(x to true)) + assertEquals(false, expr(x to false)) } } From e6c6925209e73a766a913450fdd9c6af11ca8f06 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 16 May 2021 22:33:53 +0300 Subject: [PATCH 353/393] Fix integration borders --- .../space/kscience/kmath/integration/GaussIntegrator.kt | 2 +- .../space/kscience/kmath/integration/GaussIntegralTest.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index 0038ca0f2..fcf47040e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -98,7 +98,7 @@ public fun GaussIntegrator.integrate( require(intervals > 0) { "Number of intervals must be positive" } val rangeSize = (range.endInclusive - range.start) / intervals val ranges = UnivariateIntegrandRanges( - (0 until intervals).map { i -> (rangeSize * i)..(rangeSize * (i + 1)) to order } + (0 until intervals).map { i -> (range.start + rangeSize * i)..(range.start + rangeSize * (i + 1)) to order } ) return integrate( UnivariateIntegrand( diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 1f9f7aedf..6195d0ac6 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -24,14 +24,14 @@ class GaussIntegralTest { @Test fun gaussUniform() { - val res = DoubleField.integrator.integrate(0.0..100.0) { x -> + val res = DoubleField.integrator.integrate(35.0..100.0) { x -> if(x in 30.0..50.0){ 1.0 } else { 0.0 } } - assertEquals(20.0, res.valueOrNull!!, 0.5) + assertEquals(15.0, res.valueOrNull!!, 0.5) } From 83b6d8fee0b4c899fe9246c3173325fc54aff48f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 16 May 2021 22:39:44 +0300 Subject: [PATCH 354/393] dump api --- build.gradle.kts | 2 +- kmath-core/api/kmath-core.api | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index e14d303fc..6e1aa76f4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.0-dev-9" + version = "0.3.0-dev-10" } subprojects { diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 7b09b668b..456b5cfba 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -500,6 +500,11 @@ public final class space/kscience/kmath/linear/LFeature : space/kscience/kmath/l public static final field INSTANCE Lspace/kscience/kmath/linear/LFeature; } +public abstract interface class space/kscience/kmath/linear/LUDecompositionFeature : space/kscience/kmath/linear/MatrixFeature { + public abstract fun getL ()Lspace/kscience/kmath/nd/Structure2D; + public abstract fun getU ()Lspace/kscience/kmath/nd/Structure2D; +} + public abstract interface class space/kscience/kmath/linear/LinearSolver { public abstract fun inverse (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public abstract fun solve (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; From dfac6aeb5ca83fdf85c8c8f355a61539df908e1a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 17 May 2021 10:10:49 +0300 Subject: [PATCH 355/393] Update CHANGELOG.md Co-authored-by: Iaroslav Postovalov <38042667+CommanderTvis@users.noreply.github.com> --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9a67a0ab..acdf9899b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,7 +30,8 @@ - Rewritten EJML module without ejml-simple - Stability of kmath-ast and kmath-kotilngrad promoted to EXPERIMENTAL. - ColumnarData returns nullable column -- Replaced MST.Symbolic by Symbol. Symbol now inherits MST +- MST is made sealed interface +- Replaced MST.Symbolic by Symbol, Symbol now implements MST ### Deprecated From 72f4d7c7e602766dcf71e3abbc0a7545e2ccb70f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 17 May 2021 10:10:54 +0300 Subject: [PATCH 356/393] Update kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt Co-authored-by: Iaroslav Postovalov <38042667+CommanderTvis@users.noreply.github.com> --- .../kotlin/space/kscience/kmath/operations/Algebra.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index aa22b8c19..3a1ec430e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -84,7 +84,7 @@ public interface Algebra { * @return an operation. */ public fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = - error("Binary operation '$operation; not defined in $this") + error("Binary operation '$operation' not defined in $this") /** * Dynamically invokes a binary operation with the certain name. From 53a6d3543fcbc11baac514f171dcd1d7e16cd8bf Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 17 May 2021 16:53:12 +0300 Subject: [PATCH 357/393] [WIP] Interpolation fix --- examples/build.gradle.kts | 2 +- .../kscience/kmath/functions/interpolate.kt | 56 +++++++++++++++++++ .../space/kscience/kmath/ejml/_generated.kt | 30 ++++------ .../kscience/kmath/functions/Piecewise.kt | 10 ++-- .../kscience/kmath/functions/Polynomial.kt | 18 +++--- .../kmath/interpolation/SplineInterpolator.kt | 15 ++--- .../interpolation/SplineInterpolatorTest.kt | 35 ++++++++++++ 7 files changed, 120 insertions(+), 46 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 90bb935b9..d095db1ba 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -43,7 +43,7 @@ dependencies { implementation("org.slf4j:slf4j-simple:1.7.30") // plotting - implementation("space.kscience:plotlykt-server:0.4.0-dev-2") + implementation("space.kscience:plotlykt-server:0.4.0") } kotlin.sourceSets.all { diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt new file mode 100644 index 000000000..54120ac50 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt @@ -0,0 +1,56 @@ +/* + * 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.interpolation.SplineInterpolator +import space.kscience.kmath.interpolation.interpolatePolynomials +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.plotly.Plotly +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.functionXY +import space.kscience.plotly.scatter +import kotlin.math.PI +import kotlin.math.sin + +fun main() { + val data = (0..10).map { + val x = it.toDouble() / 5 * PI + x to sin(x) + } + + val polynomial: PiecewisePolynomial = SplineInterpolator( + DoubleField, ::DoubleBuffer + ).interpolatePolynomials(data) + + val function = polynomial.asFunction(DoubleField, 0.0) + + val cmInterpolate = org.apache.commons.math3.analysis.interpolation.SplineInterpolator().interpolate( + data.map { it.first }.toDoubleArray(), + data.map { it.second }.toDoubleArray() + ) + + println(function(2.0)) + println(cmInterpolate.value(2.0)) + +// +// Plotly.plot { +// scatter { +// name = "interpolated" +// x.numbers = data.map { it.first } +// y.numbers = x.doubles.map { function(it) } +// } +// scatter { +// name = "original" +// functionXY(0.0..(2 * PI), 0.1) { sin(it) } +// } +// scatter { +// name = "cm" +// x.numbers = data.map { it.first } +// y.numbers = x.doubles.map { cmInterpolate.value(it) } +// } +// }.makeFile() +} \ No newline at end of file diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt index 139c55697..6f74ab24f 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt @@ -8,28 +8,18 @@ package space.kscience.kmath.ejml import org.ejml.data.* -import org.ejml.dense.row.CommonOps_DDRM -import org.ejml.dense.row.CommonOps_FDRM -import org.ejml.dense.row.factory.DecompositionFactory_DDRM -import org.ejml.dense.row.factory.DecompositionFactory_FDRM -import org.ejml.sparse.FillReducing -import org.ejml.sparse.csc.CommonOps_DSCC -import org.ejml.sparse.csc.CommonOps_FSCC -import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC -import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC -import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC -import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC import space.kscience.kmath.linear.* +import space.kscience.kmath.operations.* +import space.kscience.kmath.structures.* +import space.kscience.kmath.misc.* +import kotlin.reflect.* +import org.ejml.dense.row.* +import org.ejml.dense.row.factory.* +import org.ejml.sparse.* +import org.ejml.sparse.csc.* +import org.ejml.sparse.csc.factory.* +import space.kscience.kmath.nd.* import space.kscience.kmath.linear.Matrix -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.StructureFeature -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.FloatField -import space.kscience.kmath.operations.invoke -import space.kscience.kmath.structures.DoubleBuffer -import space.kscience.kmath.structures.FloatBuffer -import kotlin.reflect.KClass -import kotlin.reflect.cast /** * [EjmlVector] specialization for [Double]. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index dae55502d..6bb2a1656 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -26,12 +26,12 @@ public fun interface Piecewise { public fun interface PiecewisePolynomial : Piecewise> /** - * Basic [Piecewise] implementation where all the pieces are ordered by the [Comparable] type instances. + * A [Piecewise] builder where all the pieces are ordered by the [Comparable] type instances. * * @param T the comparable piece key type. + * @param delimiter the initial piecewise separator */ -public class OrderedPiecewisePolynomial>(delimiter: T) : - PiecewisePolynomial { +public class OrderedPiecewisePolynomial>(delimiter: T) : PiecewisePolynomial { private val delimiters: MutableList = arrayListOf(delimiter) private val pieces: MutableList> = arrayListOf() @@ -64,9 +64,7 @@ public class OrderedPiecewisePolynomial>(delimiter: T) : return null else { for (index in 1 until delimiters.size) - if (arg < delimiters[index]) - return pieces[index - 1] - + if (arg < delimiters[index]) return pieces[index - 1] error("Piece not found") } } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index efae71b0e..325010f99 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -19,7 +19,9 @@ import kotlin.math.pow * * @param coefficients constant is the leftmost coefficient. */ -public class Polynomial(public val coefficients: List) +public class Polynomial(public val coefficients: List){ + override fun toString(): String = "Polynomial$coefficients" +} /** * Returns a [Polynomial] instance with given [coefficients]. @@ -34,19 +36,15 @@ public fun Polynomial.value(): Double = coefficients.reduceIndexed { ind /** * Evaluates the value of the given polynomial for given argument. + * https://en.wikipedia.org/wiki/Horner%27s_method */ public fun > Polynomial.value(ring: C, arg: T): T = ring { if (coefficients.isEmpty()) return@ring zero - var res = coefficients.first() - var powerArg = arg - - for (index in 1 until coefficients.size) { - res += coefficients[index] * powerArg - // recalculating power on each step to avoid power costs on long polynomials - powerArg *= arg + var result: T = coefficients.last() + for (j in coefficients.size - 2 downTo 0) { + result = (arg * result) + coefficients[j] } - - res + return result } /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index 2d2ff6f26..fc341e019 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -34,19 +34,16 @@ public class SplineInterpolator>( // Number of intervals. The number of data points is n + 1. val n = points.size - 1 // Differences between knot points - val h = bufferFactory(points.size) { i -> points.x[i + 1] - points.x[i] } - val mu = bufferFactory(points.size - 1) { zero } - val z = bufferFactory(points.size) { zero } + val h = bufferFactory(n) { i -> points.x[i + 1] - points.x[i] } + val mu = bufferFactory(n) { zero } + val z = bufferFactory(n + 1) { zero } for (i in 1 until n) { val g = 2.0 * (points.x[i + 1] - points.x[i - 1]) - h[i - 1] * mu[i - 1] mu[i] = h[i] / g - - z[i] = (3.0 * (points.y[i + 1] * h[i - 1] - - points.x[i] * (points.x[i + 1] - points.x[i - 1]) - + points.y[i - 1] * h[i]) / (h[i - 1] * h[i]) - - h[i - 1] * z[i - 1] - ) / g + z[i] = + ((points.y[i + 1] * h[i - 1] - points.y[i] * (points.x[i + 1] - points.x[i - 1]) + points.y[i - 1] * h[i]) * 3.0 / + (h[i - 1] * h[i]) - h[i - 1] * z[i - 1]) / g } // cubic spline coefficients -- b is linear, c quadratic, d is cubic (original y's are constants) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt new file mode 100644 index 000000000..c3bd8195a --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt @@ -0,0 +1,35 @@ +/* + * 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.interpolation + +import space.kscience.kmath.functions.PiecewisePolynomial +import space.kscience.kmath.functions.asFunction +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.structures.DoubleBuffer +import kotlin.math.PI +import kotlin.math.sin +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class SplineInterpolatorTest { + @Test + fun testInterpolation() { + val data = (0..10).map { + val x = it.toDouble() / 5 * PI + x to sin(x) + } + + val polynomial: PiecewisePolynomial = SplineInterpolator( + DoubleField, ::DoubleBuffer + ).interpolatePolynomials(data) + + val function = polynomial.asFunction(DoubleField) + assertEquals(null, function(-1.0)) + assertEquals(sin(0.5), function(0.5)!!, 0.1) + assertEquals(sin(1.5), function(1.5)!!, 0.1) + assertEquals(sin(2.0), function(2.0)!!, 0.1) + } +} From d45d44f96d87596594b9f60935b742f2a407b6df Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 17 May 2021 21:55:32 +0300 Subject: [PATCH 358/393] Fix Interpolation --- .../kscience/kmath/functions/interpolate.kt | 35 +++++++++---------- .../space/kscience/kmath/ejml/_generated.kt | 30 ++++++++++------ .../kmath/interpolation/SplineInterpolator.kt | 19 ++++++++-- .../interpolation/SplineInterpolatorTest.kt | 15 ++++---- 4 files changed, 59 insertions(+), 40 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt index 54120ac50..69ba80fb6 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt @@ -33,24 +33,21 @@ fun main() { data.map { it.second }.toDoubleArray() ) - println(function(2.0)) - println(cmInterpolate.value(2.0)) -// -// Plotly.plot { -// scatter { -// name = "interpolated" -// x.numbers = data.map { it.first } -// y.numbers = x.doubles.map { function(it) } -// } -// scatter { -// name = "original" -// functionXY(0.0..(2 * PI), 0.1) { sin(it) } -// } -// scatter { -// name = "cm" -// x.numbers = data.map { it.first } -// y.numbers = x.doubles.map { cmInterpolate.value(it) } -// } -// }.makeFile() + Plotly.plot { + scatter { + name = "interpolated" + x.numbers = data.map { it.first } + y.numbers = x.doubles.map { function(it) } + } + scatter { + name = "original" + functionXY(0.0..(2 * PI), 0.1) { sin(it) } + } + scatter { + name = "cm" + x.numbers = data.map { it.first } + y.numbers = x.doubles.map { cmInterpolate.value(it) } + } + }.makeFile() } \ No newline at end of file diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt index 6f74ab24f..139c55697 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt @@ -8,18 +8,28 @@ package space.kscience.kmath.ejml import org.ejml.data.* +import org.ejml.dense.row.CommonOps_DDRM +import org.ejml.dense.row.CommonOps_FDRM +import org.ejml.dense.row.factory.DecompositionFactory_DDRM +import org.ejml.dense.row.factory.DecompositionFactory_FDRM +import org.ejml.sparse.FillReducing +import org.ejml.sparse.csc.CommonOps_DSCC +import org.ejml.sparse.csc.CommonOps_FSCC +import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC +import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC +import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC +import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC import space.kscience.kmath.linear.* -import space.kscience.kmath.operations.* -import space.kscience.kmath.structures.* -import space.kscience.kmath.misc.* -import kotlin.reflect.* -import org.ejml.dense.row.* -import org.ejml.dense.row.factory.* -import org.ejml.sparse.* -import org.ejml.sparse.csc.* -import org.ejml.sparse.csc.factory.* -import space.kscience.kmath.nd.* import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.StructureFeature +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.FloatField +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.FloatBuffer +import kotlin.reflect.KClass +import kotlin.reflect.cast /** * [EjmlVector] specialization for [Double]. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index fc341e019..c3d6ffae7 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -10,8 +10,10 @@ import space.kscience.kmath.functions.OrderedPiecewisePolynomial import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.MutableBufferFactory /** @@ -56,10 +58,23 @@ public class SplineInterpolator>( val a = points.y[j] val b = (points.y[j + 1] - points.y[j]) / h[j] - h[j] * (cOld + 2.0 * c) / 3.0 val d = (cOld - c) / (3.0 * h[j]) - val polynomial = Polynomial(a, b, c, d) + val x0 = points.x[j] + val x02 = x0 * x0 + val x03 = x02 * x0 + //Shift coefficients to represent absolute polynomial instead of one with an offset + val polynomial = Polynomial( + a - b * x0 + c * x02 - d * x03, + b - 2*c*x0 + 3*d*x02, + c - 3*d*x0, + d + ) cOld = c - putLeft(points.x[j], polynomial) + putLeft(x0, polynomial) } } } + + public companion object { + public val double: SplineInterpolator = SplineInterpolator(DoubleField, ::DoubleBuffer) + } } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt index c3bd8195a..3adaab2d1 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt @@ -8,7 +8,6 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.asFunction import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.structures.DoubleBuffer import kotlin.math.PI import kotlin.math.sin import kotlin.test.Test @@ -22,14 +21,12 @@ internal class SplineInterpolatorTest { x to sin(x) } - val polynomial: PiecewisePolynomial = SplineInterpolator( - DoubleField, ::DoubleBuffer - ).interpolatePolynomials(data) + val polynomial: PiecewisePolynomial = SplineInterpolator.double.interpolatePolynomials(data) - val function = polynomial.asFunction(DoubleField) - assertEquals(null, function(-1.0)) - assertEquals(sin(0.5), function(0.5)!!, 0.1) - assertEquals(sin(1.5), function(1.5)!!, 0.1) - assertEquals(sin(2.0), function(2.0)!!, 0.1) + val function = polynomial.asFunction(DoubleField, Double.NaN) + assertEquals(Double.NaN, function(-1.0)) + assertEquals(sin(0.5), function(0.5), 0.1) + assertEquals(sin(1.5), function(1.5), 0.1) + assertEquals(sin(2.0), function(2.0), 0.1) } } From 8b92db9923adfe334ae472a8d6d525802241113f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 18 May 2021 10:07:55 +0300 Subject: [PATCH 359/393] bump version --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6e1aa76f4..93f5059ff 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.0-dev-10" + version = "0.3.0-dev-11" } subprojects { From a67c112793fc2f86964e785182f83ee92aca568a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 18 May 2021 10:22:33 +0300 Subject: [PATCH 360/393] add xor --- kmath-core/api/kmath-core.api | 5 +++++ .../kotlin/space/kscience/kmath/expressions/MstAlgebra.kt | 2 ++ .../space/kscience/kmath/operations/LogicAlgebra.kt | 8 ++++++++ 3 files changed, 15 insertions(+) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index ead4b96b5..b424b59ff 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -522,6 +522,11 @@ public final class space/kscience/kmath/linear/LFeature : space/kscience/kmath/l public static final field INSTANCE Lspace/kscience/kmath/linear/LFeature; } +public abstract interface class space/kscience/kmath/linear/LUDecompositionFeature : space/kscience/kmath/linear/MatrixFeature { + public abstract fun getL ()Lspace/kscience/kmath/nd/Structure2D; + public abstract fun getU ()Lspace/kscience/kmath/nd/Structure2D; +} + public abstract interface class space/kscience/kmath/linear/LinearSolver { public abstract fun inverse (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public abstract fun solve (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt index fb2e38449..4729f19ea 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt @@ -177,4 +177,6 @@ public object MstLogicAlgebra : LogicAlgebra { override fun MST.and(other: MST): MST = MST.Binary(Boolean::and.name, this, other) override fun MST.or(other: MST): MST = MST.Binary(Boolean::or.name, this, other) + + override fun MST.xor(other: MST): MST = MST.Binary(Boolean::xor.name, this, other) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt index 406967897..9037525e1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt @@ -54,6 +54,12 @@ public interface LogicAlgebra : Algebra { */ public infix fun T.or(other: T): T + /** + * Logic 'xor' + */ + public infix fun T.xor(other: T): T + + public companion object { public val TRUE: Symbol by symbol public val FALSE: Symbol by symbol @@ -74,4 +80,6 @@ public object BooleanAlgebra : LogicAlgebra { override fun Boolean.and(other: Boolean): Boolean = this && other override fun Boolean.or(other: Boolean): Boolean = this || other + + override fun Boolean.xor(other: Boolean): Boolean = this xor other } \ No newline at end of file From b4dd4380c070e22a61691a1f7a5f0245b2ddb4b2 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 18 May 2021 18:02:13 +0700 Subject: [PATCH 361/393] Hard code specific imports in codegen --- .../kmath/ejml/codegen/ejmlCodegen.kt | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt index e4b157973..5da7d0f67 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt @@ -369,19 +369,29 @@ fun ejmlCodegen(outputFile: String): Unit = File(outputFile).run { it.appendLine() it.appendLine("package space.kscience.kmath.ejml") it.appendLine() - it.appendLine("import org.ejml.data.*") - it.appendLine("import space.kscience.kmath.linear.*") - it.appendLine("import space.kscience.kmath.operations.*") - it.appendLine("import space.kscience.kmath.structures.*") - it.appendLine("import space.kscience.kmath.misc.*") - it.appendLine("import kotlin.reflect.*") - it.appendLine("import org.ejml.dense.row.*") - it.appendLine("import org.ejml.dense.row.factory.*") - it.appendLine("import org.ejml.sparse.*") - it.appendLine("import org.ejml.sparse.csc.*") - it.appendLine("import org.ejml.sparse.csc.factory.*") - it.appendLine("import space.kscience.kmath.nd.*") - it.appendLine("import space.kscience.kmath.linear.Matrix") + it.appendLine("""import org.ejml.data.* +import org.ejml.dense.row.CommonOps_DDRM +import org.ejml.dense.row.CommonOps_FDRM +import org.ejml.dense.row.factory.DecompositionFactory_DDRM +import org.ejml.dense.row.factory.DecompositionFactory_FDRM +import org.ejml.sparse.FillReducing +import org.ejml.sparse.csc.CommonOps_DSCC +import org.ejml.sparse.csc.CommonOps_FSCC +import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC +import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC +import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC +import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC +import space.kscience.kmath.linear.* +import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.StructureFeature +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.FloatField +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.FloatBuffer +import kotlin.reflect.KClass +import kotlin.reflect.cast""") it.appendLine() it.appendEjmlVector("Double", "DMatrix") it.appendEjmlVector("Float", "FMatrix") From 08982855426eefe6ba2cf0987b1da732abba0064 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 19 May 2021 12:58:01 +0300 Subject: [PATCH 362/393] Removed Any restriction on polynomials --- CHANGELOG.md | 1 + .../space/kscience/kmath/functions/integrate.kt | 4 ++-- .../kmath/functions/matrixIntegration.kt | 4 ++-- .../kscience/kmath/functions/Polynomial.kt | 14 ++++++++------ .../kmath/integration/GaussIntegrator.kt | 13 +++++++------ .../kmath/integration/SimpsonIntegrator.kt | 17 +++++++++++++++++ .../kmath/integration/UnivariateIntegrand.kt | 10 ++++++++++ .../kmath/integration/GaussIntegralTest.kt | 4 ++-- settings.gradle.kts | 2 +- 9 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index acdf9899b..c5acd4660 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ - ColumnarData returns nullable column - MST is made sealed interface - Replaced MST.Symbolic by Symbol, Symbol now implements MST +- Removed Any restriction on polynomials ### Deprecated diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt index 8d5349bce..f60b1ab45 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.functions +import space.kscience.kmath.integration.gaussIntegrator import space.kscience.kmath.integration.integrate -import space.kscience.kmath.integration.integrator import space.kscience.kmath.integration.value import space.kscience.kmath.operations.DoubleField import kotlin.math.pow @@ -16,7 +16,7 @@ fun main() { val function: UnivariateFunction = { x -> 3 * x.pow(2) + 2 * x + 1 } //get the result of the integration - val result = DoubleField.integrator.integrate(0.0..10.0, function = function) + val result = DoubleField.gaussIntegrator.integrate(0.0..10.0, function = function) //the value is nullable because in some cases the integration could not succeed println(result.value) diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt index 601a0e3c4..2619d3d74 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.functions +import space.kscience.kmath.integration.gaussIntegrator import space.kscience.kmath.integration.integrate -import space.kscience.kmath.integration.integrator import space.kscience.kmath.integration.value import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.nd @@ -25,7 +25,7 @@ fun main(): Unit = DoubleField { val function: (Double) -> StructureND = { x: Double -> 3 * number(x).pow(2) + 2 * diagonal(x) + 1 } //get the result of the integration - val result = integrator.integrate(0.0..10.0, function = function) + val result = gaussIntegrator.integrate(0.0..10.0, function = function) //the value is nullable because in some cases the integration could not succeed println(result.value) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 325010f99..427a17385 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -19,7 +19,7 @@ import kotlin.math.pow * * @param coefficients constant is the leftmost coefficient. */ -public class Polynomial(public val coefficients: List){ +public class Polynomial(public val coefficients: List){ override fun toString(): String = "Polynomial$coefficients" } @@ -27,7 +27,7 @@ public class Polynomial(public val coefficients: List){ * Returns a [Polynomial] instance with given [coefficients]. */ @Suppress("FunctionName") -public fun Polynomial(vararg coefficients: T): Polynomial = Polynomial(coefficients.toList()) +public fun Polynomial(vararg coefficients: T): Polynomial = Polynomial(coefficients.toList()) /** * Evaluates the value of the given double polynomial for given double argument. @@ -38,7 +38,7 @@ public fun Polynomial.value(): Double = coefficients.reduceIndexed { ind * Evaluates the value of the given polynomial for given argument. * https://en.wikipedia.org/wiki/Horner%27s_method */ -public fun > Polynomial.value(ring: C, arg: T): T = ring { +public fun > Polynomial.value(ring: C, arg: T): T = ring { if (coefficients.isEmpty()) return@ring zero var result: T = coefficients.last() for (j in coefficients.size - 2 downTo 0) { @@ -50,7 +50,9 @@ public fun > Polynomial.value(ring: C, arg: T): T = ring /** * Represent the polynomial as a regular context-less function. */ -public fun > Polynomial.asFunction(ring: C): (T) -> T = { value(ring, it) } +public fun > Polynomial.asFunction(ring: C): (T) -> T = { value(ring, it) } + +//public fun /** * Space of polynomials. @@ -59,7 +61,7 @@ public fun > Polynomial.asFunction(ring: C): (T) -> T = * @param C the intersection of [Ring] of [T] and [ScaleOperations] of [T]. * @param ring the [C] instance. */ -public class PolynomialSpace( +public class PolynomialSpace( private val ring: C, ) : Group>, ScaleOperations> where C : Ring, C : ScaleOperations { public override val zero: Polynomial = Polynomial(emptyList()) @@ -87,7 +89,7 @@ public class PolynomialSpace( public operator fun Polynomial.invoke(arg: T): T = value(ring, arg) } -public inline fun C.polynomial(block: PolynomialSpace.() -> R): R where C : Ring, C : ScaleOperations { +public inline fun C.polynomial(block: PolynomialSpace.() -> R): R where C : Ring, C : ScaleOperations { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return PolynomialSpace(this).block() } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index fcf47040e..26757ae68 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -20,6 +20,11 @@ public class UnivariateIntegrandRanges(public val ranges: List( public val algebra: Field, @@ -73,13 +78,9 @@ public class GaussIntegrator( /** * Create a Gauss-Legendre integrator for this field - * Following integrand features are accepted: - * * [GaussIntegratorRuleFactory] - A factory for computing the Gauss integration rule. By default uses [GaussLegendreRuleFactory] - * * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. - * * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 10 points. - * * [UnivariateIntegrandRanges] - Set of ranges and number of points per range. Defaults to given [IntegrationRange] and [IntegrandMaxCalls] + * @see [GaussIntegrator] */ -public val Field.integrator: GaussIntegrator get() = GaussIntegrator(this) +public val Field.gaussIntegrator: GaussIntegrator get() = GaussIntegrator(this) /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt new file mode 100644 index 000000000..526d4d35d --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt @@ -0,0 +1,17 @@ +/* + * 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.integration + +import space.kscience.kmath.operations.Ring + + +public class SimpsonIntegrator( + public val algebra: Ring, +) : UnivariateIntegrator { + override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index 3cafc9782..c03cc8df0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -45,6 +45,16 @@ public val UnivariateIntegrand.valueOrNull: T? get() = getFeature UnivariateIntegrand.value: T get() = valueOrNull ?: error("No value in the integrand") +/** + * A shortcut method to integrate a [function] with additional [features]. Range must be provided in features. + * The [function] is placed in the end position to allow passing a lambda. + */ +@UnstableKMathAPI +public fun UnivariateIntegrator.integrate( + vararg features: IntegrandFeature, + function: (Double) -> T, +): UnivariateIntegrand = integrate(UnivariateIntegrand(function, *features)) + /** * A shortcut method to integrate a [function] in [range] with additional [features]. * The [function] is placed in the end position to allow passing a lambda. diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 6195d0ac6..5c9241120 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -16,7 +16,7 @@ import kotlin.test.assertEquals class GaussIntegralTest { @Test fun gaussSin() { - val res = DoubleField.integrator.integrate(0.0..2 * PI) { x -> + val res = DoubleField.gaussIntegrator.integrate(0.0..2 * PI) { x -> sin(x) } assertEquals(0.0, res.valueOrNull!!, 1e-2) @@ -24,7 +24,7 @@ class GaussIntegralTest { @Test fun gaussUniform() { - val res = DoubleField.integrator.integrate(35.0..100.0) { x -> + val res = DoubleField.gaussIntegrator.integrate(35.0..100.0) { x -> if(x in 30.0..50.0){ 1.0 } else { diff --git a/settings.gradle.kts b/settings.gradle.kts index 7ebfe1f59..cc9eb4860 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,7 +5,7 @@ pluginManagement { maven("https://repo.kotlin.link") } - val toolsVersion = "0.9.7" + val toolsVersion = "0.9.8" val kotlinVersion = "1.5.0" plugins { From 8a07140f7c91e3ff0cf18cdc6ef95b9ac02e59da Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 19 May 2021 22:35:06 +0300 Subject: [PATCH 363/393] Minor piecewise rework --- .../kscience/kmath/functions/interpolate.kt | 2 + .../kscience/kmath/functions/Piecewise.kt | 34 +++++++++---- .../kscience/kmath/functions/Polynomial.kt | 48 +++++++++++++++---- .../kmath/interpolation/LinearInterpolator.kt | 3 +- .../kmath/interpolation/SplineInterpolator.kt | 3 +- .../kmath/functions/PolynomialTest.kt | 17 +++++++ .../kmath/histogram/TreeHistogramSpace.kt | 11 ++--- .../kmath/histogram/UnivariateHistogram.kt | 5 +- 8 files changed, 91 insertions(+), 32 deletions(-) create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt index 69ba80fb6..b05c003a6 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt @@ -10,12 +10,14 @@ import space.kscience.kmath.interpolation.interpolatePolynomials import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.DoubleBuffer import space.kscience.plotly.Plotly +import space.kscience.plotly.UnstablePlotlyAPI import space.kscience.plotly.makeFile import space.kscience.plotly.models.functionXY import space.kscience.plotly.scatter import kotlin.math.PI import kotlin.math.sin +@OptIn(UnstablePlotlyAPI::class) fun main() { val data = (0..10).map { val x = it.toDouble() / 5 * PI diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index 6bb2a1656..dd9c571b0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -22,8 +22,20 @@ public fun interface Piecewise { /** * Represents piecewise-defined function where all the sub-functions are polynomials. + * @param pieces An ordered list of range-polynomial pairs. The list does not in general guarantee that there are no "holes" in it. */ -public fun interface PiecewisePolynomial : Piecewise> +public class PiecewisePolynomial>( + public val pieces: List, Polynomial>>, +) : Piecewise> { + + public override fun findPiece(arg: T): Polynomial? { + return if (arg < pieces.first().first.start || arg >= pieces.last().first.endInclusive) + null + else { + pieces.firstOrNull { arg in it.first }?.second + } + } +} /** * A [Piecewise] builder where all the pieces are ordered by the [Comparable] type instances. @@ -31,7 +43,7 @@ public fun interface PiecewisePolynomial : Piecewise> * @param T the comparable piece key type. * @param delimiter the initial piecewise separator */ -public class OrderedPiecewisePolynomial>(delimiter: T) : PiecewisePolynomial { +public class PiecewiseBuilder>(delimiter: T) { private val delimiters: MutableList = arrayListOf(delimiter) private val pieces: MutableList> = arrayListOf() @@ -59,17 +71,19 @@ public class OrderedPiecewisePolynomial>(delimiter: T) : Piece pieces.add(0, piece) } - public override fun findPiece(arg: T): Polynomial? { - if (arg < delimiters.first() || arg >= delimiters.last()) - return null - else { - for (index in 1 until delimiters.size) - if (arg < delimiters[index]) return pieces[index - 1] - error("Piece not found") - } + public fun build(): PiecewisePolynomial { + return PiecewisePolynomial(delimiters.zipWithNext { l, r -> l..r }.zip(pieces)) } } +/** + * A builder for [PiecewisePolynomial] + */ +public fun > PiecewisePolynomial( + startingPoint: T, + builder: PiecewiseBuilder.() -> Unit, +): PiecewisePolynomial = PiecewiseBuilder(startingPoint).apply(builder).build() + /** * Return a value of polynomial function with given [ring] an given [arg] or null if argument is outside of piecewise * definition. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 427a17385..4976befcb 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -5,10 +5,8 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.Group -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.invoke +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.math.max @@ -19,7 +17,7 @@ import kotlin.math.pow * * @param coefficients constant is the leftmost coefficient. */ -public class Polynomial(public val coefficients: List){ +public class Polynomial(public val coefficients: List) { override fun toString(): String = "Polynomial$coefficients" } @@ -32,7 +30,9 @@ public fun Polynomial(vararg coefficients: T): Polynomial = Polynomial(co /** * Evaluates the value of the given double polynomial for given double argument. */ -public fun Polynomial.value(): Double = coefficients.reduceIndexed { index, acc, d -> acc + d.pow(index) } +public fun Polynomial.value(arg: Double): Double = coefficients.reduceIndexed { index, acc, c -> + acc + c * arg.pow(index) +} /** * Evaluates the value of the given polynomial for given argument. @@ -50,9 +50,38 @@ public fun > Polynomial.value(ring: C, arg: T): T = ring { /** * Represent the polynomial as a regular context-less function. */ -public fun > Polynomial.asFunction(ring: C): (T) -> T = { value(ring, it) } +public fun > Polynomial.asFunction(ring: C): (T) -> T = { value(ring, it) } -//public fun +/** + * Create a polynomial witch represents differentiated version of this polynomial + */ +@UnstableKMathAPI +public fun Polynomial.differentiate( + algebra: A, +): Polynomial where A : Ring, A : NumericAlgebra = algebra { + Polynomial(coefficients.drop(1).mapIndexed { index, t -> number(index) * t }) +} + +/** + * Create a polynomial witch represents indefinite integral version of this polynomial + */ +@UnstableKMathAPI +public fun Polynomial.integrate( + algebra: A, +): Polynomial where A : Field, A : NumericAlgebra = algebra { + Polynomial(coefficients.mapIndexed { index, t -> t / number(index) }) +} + +/** + * Compute a definite integral of a given polynomial in a [range] + */ +@UnstableKMathAPI +public fun , A> Polynomial.integrate( + algebra: A, + range: ClosedRange, +): T where A : Field, A : NumericAlgebra = algebra { + value(algebra, range.endInclusive) - value(algebra, range.start) +} /** * Space of polynomials. @@ -87,6 +116,9 @@ public class PolynomialSpace( * Evaluates the polynomial for the given value [arg]. */ public operator fun Polynomial.invoke(arg: T): T = value(ring, arg) + + public fun Polynomial.asFunction(): (T) -> T = asFunction(ring) + } public inline fun C.polynomial(block: PolynomialSpace.() -> R): R where C : Ring, C : ScaleOperations { diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt index 3fbf6157e..24c049647 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt @@ -6,7 +6,6 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.data.XYColumnarData -import space.kscience.kmath.functions.OrderedPiecewisePolynomial import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.misc.UnstableKMathAPI @@ -28,7 +27,7 @@ public class LinearInterpolator>(public override val algebra: require(points.size > 0) { "Point array should not be empty" } insureSorted(points) - OrderedPiecewisePolynomial(points.x[0]).apply { + PiecewisePolynomial(points.x[0]) { for (i in 0 until points.size - 1) { val slope = (points.y[i + 1] - points.y[i]) / (points.x[i + 1] - points.x[i]) val const = points.y[i] - slope * points.x[i] diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index c3d6ffae7..bf291c315 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -6,7 +6,6 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.data.XYColumnarData -import space.kscience.kmath.functions.OrderedPiecewisePolynomial import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.misc.UnstableKMathAPI @@ -50,7 +49,7 @@ public class SplineInterpolator>( // cubic spline coefficients -- b is linear, c quadratic, d is cubic (original y's are constants) - OrderedPiecewisePolynomial(points.x[points.size - 1]).apply { + PiecewisePolynomial(points.x[points.size - 1]) { var cOld = zero for (j in n - 1 downTo 0) { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt new file mode 100644 index 000000000..05c16d17e --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt @@ -0,0 +1,17 @@ +/* + * 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.test.Test +import kotlin.test.assertEquals + +class PolynomialTest { + @Test + fun testIntegration() { + val polynomial = Polynomial(1.0, -2.0, 1.0) + assertEquals(0.0, polynomial.value(1.0), 0.001) + } +} \ No newline at end of file diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt index 5a217f6c2..6ae8b5ee3 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt @@ -28,7 +28,6 @@ private fun > TreeMap.getBin(val @UnstableKMathAPI public class TreeHistogram( - override val context: TreeHistogramSpace, private val binMap: TreeMap, ) : UnivariateHistogram { override fun get(value: Double): UnivariateBin? = binMap.getBin(value) @@ -79,15 +78,15 @@ public class TreeHistogramSpace( val count = binCounter.counter.value resBins[key] = UnivariateBin(binCounter.domain, count, sqrt(count)) } - return TreeHistogram(this, resBins) + return TreeHistogram(resBins) } override fun add( a: UnivariateHistogram, b: UnivariateHistogram, ): UnivariateHistogram { - require(a.context == this) { "Histogram $a does not belong to this context" } - require(b.context == this) { "Histogram $b does not belong to this context" } +// require(a.context == this) { "Histogram $a does not belong to this context" } +// require(b.context == this) { "Histogram $b does not belong to this context" } val bins = TreeMap().apply { (a.bins.map { it.domain } union b.bins.map { it.domain }).forEach { def -> put(def.center, @@ -100,7 +99,7 @@ public class TreeHistogramSpace( ) } } - return TreeHistogram(this, bins) + return TreeHistogram(bins) } override fun scale(a: UnivariateHistogram, value: Double): UnivariateHistogram { @@ -116,7 +115,7 @@ public class TreeHistogramSpace( } } - return TreeHistogram(this, bins) + return TreeHistogram(bins) } override fun UnivariateHistogram.unaryMinus(): UnivariateHistogram = this * (-1) diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt index 645116ade..70125e22e 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt @@ -7,8 +7,6 @@ package space.kscience.kmath.histogram import space.kscience.kmath.domains.UnivariateDomain import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Group -import space.kscience.kmath.operations.GroupElement import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asSequence @@ -35,8 +33,7 @@ public class UnivariateBin( } @OptIn(UnstableKMathAPI::class) -public interface UnivariateHistogram : Histogram, - GroupElement> { +public interface UnivariateHistogram : Histogram{ public operator fun get(value: Double): UnivariateBin? public override operator fun get(point: Buffer): UnivariateBin? = get(point[0]) From d7a4228f5f5da85d425d6778080f8ab38488ee0e Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 20 May 2021 19:43:29 +0700 Subject: [PATCH 364/393] Add out variance to StructureND and some related types, make some unrelated changes --- CHANGELOG.md | 19 ++++++++++--------- README.md | 15 +++++++-------- docs/templates/README-TEMPLATE.md | 2 +- .../space/kscience/kmath/tensors/PCA.kt | 2 +- kmath-ast/README.md | 6 +++--- kmath-complex/README.md | 6 +++--- kmath-core/README.md | 6 +++--- .../kscience/kmath/linear/MatrixBuilder.kt | 2 +- .../kscience/kmath/linear/MatrixWrapper.kt | 13 ++++++------- .../kscience/kmath/linear/VirtualMatrix.kt | 2 +- .../space/kscience/kmath/nd/AlgebraND.kt | 8 ++++---- .../kscience/kmath/nd/BufferAlgebraND.kt | 2 +- .../space/kscience/kmath/nd/BufferND.kt | 2 +- .../space/kscience/kmath/nd/Structure1D.kt | 12 ++++++++---- .../space/kscience/kmath/nd/Structure2D.kt | 4 ++-- .../space/kscience/kmath/nd/StructureND.kt | 6 ++---- .../space/kscience/kmath/structures/Buffer.kt | 2 +- .../kmath/structures/FlaggedBuffer.kt | 2 +- .../kmath/expressions/SimpleAutoDiffTest.kt | 2 +- .../kmath/structures/LazyStructureND.kt | 2 +- kmath-ejml/README.md | 6 +++--- .../space/kscience/kmath/ejml/EjmlMatrix.kt | 2 +- kmath-for-real/README.md | 6 +++--- kmath-functions/README.md | 6 +++--- kmath-kotlingrad/README.md | 8 ++++---- kmath-memory/build.gradle.kts | 2 +- kmath-nd4j/README.md | 6 +++--- kmath-tensors/README.md | 14 +++++++------- 28 files changed, 83 insertions(+), 82 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5acd4660..274a403b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,19 +20,20 @@ - Space is replaced by Group. Space is reserved for vector spaces. - VectorSpace is now a vector space - Buffer factories for primitives moved to MutableBuffer.Companion -- NDStructure and NDAlgebra to StructureND and AlgebraND respectively -- Real -> Double +- Rename `NDStructure` and `NDAlgebra` to `StructureND` and `AlgebraND` respectively +- `Real` -> `Double` - DataSets are moved from functions to core - Redesign advanced Chain API -- Redesign MST. Remove MSTExpression. -- Move MST to core +- Redesign `MST`. Remove `MstExpression`. +- Move `MST` to core - Separated benchmarks and examples -- Rewritten EJML module without ejml-simple -- Stability of kmath-ast and kmath-kotilngrad promoted to EXPERIMENTAL. +- Rewrite `kmath-ejml` without `ejml-simple` artifact, support sparse matrices +- Promote stability of kmath-ast and kmath-kotlingrad to EXPERIMENTAL. - ColumnarData returns nullable column -- MST is made sealed interface -- Replaced MST.Symbolic by Symbol, Symbol now implements MST -- Removed Any restriction on polynomials +- `MST` is made sealed interface +- Replace `MST.Symbolic` by `Symbol`, `Symbol` now implements MST +- Remove Any restriction on polynomials +- Add `out` variance to type parameters of `StructureND` and its implementations where possible ### Deprecated diff --git a/README.md b/README.md index 519472a69..9117582ac 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ KMath is a modular library. Different modules provide different features with di * **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version. * **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked with `@UnstableKmathAPI` or other stability warning annotations. -* **DEVELOPMENT**. API breaking genrally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool. +* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool. * **STABLE**. The API stabilized. Breaking changes are allowed only in major releases. @@ -213,7 +213,7 @@ One can still use generic algebras though. > > **Features:** > - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : MST based DifferentiableExpression. -> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : Conversions between Kotlin∇'s SFun and MST +> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : Conversions between Kotlin∇'s SFun and MST
@@ -247,10 +247,9 @@ One can still use generic algebras though. > **Maturity**: PROTOTYPE > > **Features:** -> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Interface for basic linear algebra operations on tensors (plus, dot, etc.) -> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Interface for advanced linear algebra operations like LU decomposition, SVD, etc. -> - [tensor algebra over Double](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s. -> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting for tensors over `Double`'s. +> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) +> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. +> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc.
@@ -294,8 +293,8 @@ repositories { } dependencies { - api("space.kscience:kmath-core:0.3.0-dev-8") - // api("space.kscience:kmath-core-jvm:0.3.0-dev-8") for jvm-specific version + api("space.kscience:kmath-core:0.3.0-dev-11") + // api("space.kscience:kmath-core-jvm:0.3.0-dev-11") for jvm-specific version } ``` diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index 99951b4d6..6bb1e9085 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -40,7 +40,7 @@ KMath is a modular library. Different modules provide different features with di * **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version. * **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked with `@UnstableKmathAPI` or other stability warning annotations. -* **DEVELOPMENT**. API breaking genrally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool. +* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool. * **STABLE**. The API stabilized. Breaking changes are allowed only in major releases. diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt index e47b87177..411e048d7 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -11,7 +11,7 @@ import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra // simple PCA -fun main() = BroadcastDoubleTensorAlgebra { // work in context with broadcast methods +fun main(): Unit = BroadcastDoubleTensorAlgebra { // work in context with broadcast methods val seed = 100500L // assume x is range from 0 until 10 diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 646ab4306..b0f2d59e5 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -10,7 +10,7 @@ Performance and visualization extensions to MST API. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-8`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-11`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0-dev-8' + implementation 'space.kscience:kmath-ast:0.3.0-dev-11' } ``` **Gradle Kotlin DSL:** @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0-dev-8") + implementation("space.kscience:kmath-ast:0.3.0-dev-11") } ``` diff --git a/kmath-complex/README.md b/kmath-complex/README.md index ee5ad416f..04431cf6c 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-8`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-11`. **Gradle:** ```gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0-dev-8' + implementation 'space.kscience:kmath-complex:0.3.0-dev-11' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0-dev-8") + implementation("space.kscience:kmath-complex:0.3.0-dev-11") } ``` diff --git a/kmath-core/README.md b/kmath-core/README.md index 7283a18ce..700eaef38 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-8`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-11`. **Gradle:** ```gradle @@ -25,7 +25,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0-dev-8' + implementation 'space.kscience:kmath-core:0.3.0-dev-11' } ``` **Gradle Kotlin DSL:** @@ -36,6 +36,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0-dev-8") + implementation("space.kscience:kmath-core:0.3.0-dev-11") } ``` diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt index e6115a1e5..72d22233a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.linear import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring -public class MatrixBuilder>( +public class MatrixBuilder>( public val linearSpace: LinearSpace, public val rows: Int, public val columns: Int, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt index 4d1180c17..16aadab3b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt @@ -16,7 +16,7 @@ import kotlin.reflect.KClass * * @param T the type of items. */ -public class MatrixWrapper internal constructor( +public class MatrixWrapper internal constructor( public val origin: Matrix, public val features: Set, ) : Matrix by origin { @@ -26,12 +26,11 @@ public class MatrixWrapper internal constructor( */ @UnstableKMathAPI @Suppress("UNCHECKED_CAST") - override fun getFeature(type: KClass): F? = features.singleOrNull { type.isInstance(it) } as? F - ?: origin.getFeature(type) + public override fun getFeature(type: KClass): F? = + features.singleOrNull(type::isInstance) as? F + ?: origin.getFeature(type) - override fun toString(): String { - return "MatrixWrapper(matrix=$origin, features=$features)" - } + public override fun toString(): String = "MatrixWrapper(matrix=$origin, features=$features)" } /** @@ -82,7 +81,7 @@ public fun LinearSpace>.zero( elementAlgebra.zero } + ZeroFeature -public class TransposedFeature(public val original: Matrix) : MatrixFeature +public class TransposedFeature(public val original: Matrix) : MatrixFeature /** * Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A` diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt index e4c2b49f0..3751bd33b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt @@ -10,7 +10,7 @@ package space.kscience.kmath.linear * * @property generator the function that provides elements. */ -public class VirtualMatrix( +public class VirtualMatrix( override val rowNum: Int, override val colNum: Int, public val generator: (i: Int, j: Int) -> T, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt index 1b3cb9e0a..93187eb41 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt @@ -26,7 +26,7 @@ public class ShapeMismatchException(public val expected: IntArray, public val ac * @param C the type of the element context. * @param N the type of the structure. */ -public interface AlgebraND> { +public interface AlgebraND> { /** * The shape of ND-structures this algebra operates on. */ @@ -121,7 +121,7 @@ internal fun > AlgebraND.checkShape(element: StructureND * @param N the type of ND structure. * @param S the type of space of structure elements. */ -public interface GroupND> : Group>, AlgebraND { +public interface GroupND> : Group>, AlgebraND { /** * Element-wise addition. * @@ -189,7 +189,7 @@ public interface GroupND> : Group>, AlgebraND> : Ring>, GroupND { +public interface RingND> : Ring>, GroupND { /** * Element-wise multiplication. * @@ -230,7 +230,7 @@ public interface RingND> : Ring>, GroupND { * @param N the type of ND structure. * @param F the type field of structure elements. */ -public interface FieldND> : Field>, RingND, ScaleOperations> { +public interface FieldND> : Field>, RingND, ScaleOperations> { /** * Element-wise division. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt index 905a48d5c..2b82a36ae 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt @@ -11,7 +11,7 @@ import space.kscience.kmath.structures.BufferFactory import kotlin.contracts.InvocationKind import kotlin.contracts.contract -public interface BufferAlgebraND> : AlgebraND { +public interface BufferAlgebraND> : AlgebraND { public val strides: Strides public val bufferFactory: BufferFactory diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt index 425808aeb..904419302 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt @@ -18,7 +18,7 @@ import space.kscience.kmath.structures.MutableBufferFactory * @param strides The strides to access elements of [Buffer] by linear indices. * @param buffer The underlying buffer. */ -public open class BufferND( +public open class BufferND( public val strides: Strides, public val buffer: Buffer, ) : StructureND { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index cc0528793..150ebf6fb 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -15,7 +15,7 @@ import kotlin.jvm.JvmInline /** * A structure that is guaranteed to be one-dimensional */ -public interface Structure1D : StructureND, Buffer { +public interface Structure1D : StructureND, Buffer { public override val dimension: Int get() = 1 public override operator fun get(index: IntArray): T { @@ -42,7 +42,7 @@ public interface MutableStructure1D : Structure1D, MutableStructureND, * A 1D wrapper for nd-structure */ @JvmInline -private value class Structure1DWrapper(val structure: StructureND) : Structure1D { +private value class Structure1DWrapper(val structure: StructureND) : Structure1D { override val shape: IntArray get() = structure.shape override val size: Int get() = structure.shape[0] @@ -68,7 +68,11 @@ private class MutableStructure1DWrapper(val structure: MutableStructureND) } @PerformancePitfall - override fun copy(): MutableBuffer = structure.elements().map { it.second }.toMutableList().asMutableBuffer() + override fun copy(): MutableBuffer = structure + .elements() + .map(Pair::second) + .toMutableList() + .asMutableBuffer() } @@ -76,7 +80,7 @@ private class MutableStructure1DWrapper(val structure: MutableStructureND) * A structure wrapper for buffer */ @JvmInline -private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D { +private value class Buffer1DWrapper(val buffer: Buffer) : Structure1D { override val shape: IntArray get() = intArrayOf(buffer.size) override val size: Int get() = buffer.size diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index 5b8183699..f353b6974 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -18,7 +18,7 @@ import kotlin.reflect.KClass * * @param T the type of items. */ -public interface Structure2D : StructureND { +public interface Structure2D : StructureND { /** * The number of rows in this structure. */ @@ -100,7 +100,7 @@ public interface MutableStructure2D : Structure2D, MutableStructureND { * A 2D wrapper for nd-structure */ @JvmInline -private value class Structure2DWrapper(val structure: StructureND) : Structure2D { +private value class Structure2DWrapper(val structure: StructureND) : Structure2D { override val shape: IntArray get() = structure.shape override val rowNum: Int get() = shape[0] diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index b9f1a063a..7fc91e321 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -24,7 +24,7 @@ public interface StructureFeature * * @param T the type of items. */ -public interface StructureND { +public interface StructureND { /** * The shape of structure, i.e. non-empty sequence of non-negative integers that specify sizes of dimensions of * this structure. @@ -213,9 +213,7 @@ public interface Strides { /** * Iterate over ND indices in a natural order */ - public fun indices(): Sequence = (0 until linearSize).asSequence().map { - index(it) - } + public fun indices(): Sequence = (0 until linearSize).asSequence().map(::index) } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index be5dfb359..82f17b807 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -283,7 +283,7 @@ public value class ReadOnlyBuffer(public val buffer: MutableBuffer) : Buff * * @param T the type of elements provided by the buffer. */ -public class VirtualBuffer(override val size: Int, private val generator: (Int) -> T) : Buffer { +public class VirtualBuffer(override val size: Int, private val generator: (Int) -> T) : Buffer { override operator fun get(index: Int): T { if (index < 0 || index >= size) throw IndexOutOfBoundsException("Expected index from 0 to ${size - 1}, but found $index") return generator(index) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt index a63f452f5..0b16a3afc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt @@ -37,7 +37,7 @@ public enum class ValueFlag(public val mask: Byte) { /** * A buffer with flagged values. */ -public interface FlaggedBuffer : Buffer { +public interface FlaggedBuffer : Buffer { public fun getFlag(index: Int): Byte } diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt index c6852cbbf..201890933 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -17,7 +17,7 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue -class SimpleAutoDiffTest { +internal class SimpleAutoDiffTest { fun dx( xBinding: Pair, diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt index 1cd16054a..ded8c9c44 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt @@ -11,7 +11,7 @@ import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.DefaultStrides import space.kscience.kmath.nd.StructureND -public class LazyStructureND( +public class LazyStructureND( public val scope: CoroutineScope, public override val shape: IntArray, public val function: suspend (IntArray) -> T, diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index cb12ef98d..79a28b824 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-8`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-11`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0-dev-8' + implementation 'space.kscience:kmath-ejml:0.3.0-dev-11' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0-dev-8") + implementation("space.kscience:kmath-ejml:0.3.0-dev-11") } ``` diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index fd43f295c..cec31eb7d 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -16,7 +16,7 @@ import space.kscience.kmath.nd.Structure2D * @property origin The underlying EJML matrix. * @author Iaroslav Postovalov */ -public abstract class EjmlMatrix(public open val origin: M) : Structure2D { +public abstract class EjmlMatrix(public open val origin: M) : Structure2D { public override val rowNum: Int get() = origin.numRows public override val colNum: Int get() = origin.numCols } diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 8b3b8e9e0..5ca805093 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-8`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-11`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0-dev-8' + implementation 'space.kscience:kmath-for-real:0.3.0-dev-11' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0-dev-8") + implementation("space.kscience:kmath-for-real:0.3.0-dev-11") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 4f592c845..2497f7102 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-8`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-11`. **Gradle:** ```gradle @@ -21,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0-dev-8' + implementation 'space.kscience:kmath-functions:0.3.0-dev-11' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0-dev-8") + implementation("space.kscience:kmath-functions:0.3.0-dev-11") } ``` diff --git a/kmath-kotlingrad/README.md b/kmath-kotlingrad/README.md index 686df3271..4393cbf8c 100644 --- a/kmath-kotlingrad/README.md +++ b/kmath-kotlingrad/README.md @@ -1,6 +1,6 @@ # Module kmath-kotlingrad -[Kotlin∇](https://github.com/breandan/kotlingrad) integration module. +[Kotlin∇](https://www.htmlsymbols.xyz/unicode/U+2207) integration module. - [differentiable-mst-expression](src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : MST based DifferentiableExpression. - [differentiable-mst-expression](src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : Conversions between Kotlin∇'s SFun and MST @@ -8,7 +8,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0-dev-8`. +The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0-dev-11`. **Gradle:** ```gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-kotlingrad:0.3.0-dev-8' + implementation 'space.kscience:kmath-kotlingrad:0.3.0-dev-11' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-kotlingrad:0.3.0-dev-8") + implementation("space.kscience:kmath-kotlingrad:0.3.0-dev-11") } ``` diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 288c61a51..4478e5b80 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -7,6 +7,6 @@ plugins { readme { maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT description = """ - An API and basic implementation for arranging objects in a continous memory block. + An API and basic implementation for arranging objects in a continuous memory block. """.trimIndent() } diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 5f33c1db1..6408be13b 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-8`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-11`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0-dev-8' + implementation 'space.kscience:kmath-nd4j:0.3.0-dev-11' } ``` **Gradle Kotlin DSL:** @@ -30,7 +30,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0-dev-8") + implementation("space.kscience:kmath-nd4j:0.3.0-dev-11") } ``` diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index affdad665..75de2bf35 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -2,14 +2,14 @@ Common linear algebra operations on tensors. - - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Interface for basic linear algebra operations on tensors (plus, dot, etc.) - - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Interface for advanced linear algebra operations like LU decomposition, SVD, etc. - - [tensor algebra over Double](src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt): Full implementation of operations for tensors over `Double`'s. - - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting for tensors over `Double`'s. + - [tensor algebra](src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.) + - [tensor algebra with broadcasting](src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting. + - [linear algebra operations](src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. + ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-8`. +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-11`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensors:0.3.0-dev-8' + implementation 'space.kscience:kmath-tensors:0.3.0-dev-11' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensors:0.3.0-dev-8") + implementation("space.kscience:kmath-tensors:0.3.0-dev-11") } ``` From 15a0258b7d860c861239d26d33528935ce98083c Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 14 May 2021 00:37:33 +0700 Subject: [PATCH 365/393] Nd4j based TensorAlgebra implementation, drop Nd4jArrayLongStructure --- .../space/kscience/kmath/nd/AlgebraND.kt | 1 - kmath-nd4j/build.gradle.kts | 20 +- .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 179 ++++++++---------- .../kscience/kmath/nd4j/Nd4jArrayIterator.kt | 6 - .../kscience/kmath/nd4j/Nd4jArrayStructure.kt | 15 +- .../kscience/kmath/nd4j/Nd4jTensorAlgebra.kt | 175 +++++++++++++++++ .../space/kscience/kmath/nd4j/arrays.kt | 1 - .../kmath/nd4j/Nd4jArrayAlgebraTest.kt | 2 +- .../kmath/nd4j/Nd4jArrayStructureTest.kt | 2 +- .../kmath/tensors/api/TensorAlgebra.kt | 22 +-- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 23 +-- 11 files changed, 280 insertions(+), 166 deletions(-) create mode 100644 kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt index 93187eb41..35bbc44f6 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt @@ -227,7 +227,6 @@ public interface RingND> : Ring>, GroupND> : Field>, RingND, ScaleOperations> { diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index bc61060db..12ea5c130 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } dependencies { - api(project(":kmath-core")) + api(project(":kmath-tensors")) api("org.nd4j:nd4j-api:1.0.0-beta7") testImplementation("org.nd4j:nd4j-native:1.0.0-beta7") testImplementation("org.nd4j:nd4j-native-platform:1.0.0-beta7") @@ -15,19 +15,7 @@ readme { description = "ND4J NDStructure implementation and according NDAlgebra classes" maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) - - feature( - id = "nd4jarraystructure", - description = "NDStructure wrapper for INDArray" - ) - - feature( - id = "nd4jarrayrings", - description = "Rings over Nd4jArrayStructure of Int and Long" - ) - - feature( - id = "nd4jarrayfields", - description = "Fields over Nd4jArrayStructure of Float and Double" - ) + feature(id = "nd4jarraystructure") { "NDStructure wrapper for INDArray" } + feature(id = "nd4jarrayrings") { "Rings over Nd4jArrayStructure of Int and Long" } + feature(id = "nd4jarrayfields") { "Fields over Nd4jArrayStructure of Float and Double" } } diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index 3cac44c47..e94bda12a 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -6,15 +6,14 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray -import org.nd4j.linalg.api.ops.impl.scalar.Pow -import org.nd4j.linalg.api.ops.impl.transforms.strict.* +import org.nd4j.linalg.api.ops.impl.transforms.strict.ACosh +import org.nd4j.linalg.api.ops.impl.transforms.strict.ASinh import org.nd4j.linalg.factory.Nd4j import org.nd4j.linalg.ops.transforms.Transforms import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* -import space.kscience.kmath.structures.* internal fun AlgebraND<*, *>.checkShape(array: INDArray): INDArray { val arrayShape = array.shape().toIntArray() @@ -29,23 +28,16 @@ internal fun AlgebraND<*, *>.checkShape(array: INDArray): INDArray { * @param T the type of ND-structure element. * @param C the type of the element context. */ -public interface Nd4jArrayAlgebra> : AlgebraND { +public sealed interface Nd4jArrayAlgebra> : AlgebraND { /** - * Wraps [INDArray] to [N]. + * Wraps [INDArray] to [Nd4jArrayStructure]. */ public fun INDArray.wrap(): Nd4jArrayStructure + /** + * Unwraps to or acquires [INDArray] from [StructureND]. + */ public val StructureND.ndArray: INDArray - get() = when { - !shape.contentEquals(this@Nd4jArrayAlgebra.shape) -> throw ShapeMismatchException( - this@Nd4jArrayAlgebra.shape, - shape - ) - this is Nd4jArrayStructure -> ndArray //TODO check strides - else -> { - TODO() - } - } public override fun produce(initializer: C.(IntArray) -> T): Nd4jArrayStructure { val struct = Nd4j.create(*shape)!!.wrap() @@ -85,7 +77,7 @@ public interface Nd4jArrayAlgebra> : AlgebraND { * @param T the type of the element contained in ND structure. * @param S the type of space of structure elements. */ -public interface Nd4JArrayGroup> : GroupND, Nd4jArrayAlgebra { +public sealed interface Nd4jArrayGroup> : GroupND, Nd4jArrayAlgebra { public override val zero: Nd4jArrayStructure get() = Nd4j.zeros(*shape).wrap() @@ -110,7 +102,7 @@ public interface Nd4JArrayGroup> : GroupND, Nd4jArrayAlgebr * @param R the type of ring of structure elements. */ @OptIn(UnstableKMathAPI::class) -public interface Nd4jArrayRing> : RingND, Nd4JArrayGroup { +public sealed interface Nd4jArrayRing> : RingND, Nd4jArrayGroup { public override val one: Nd4jArrayStructure get() = Nd4j.ones(*shape).wrap() @@ -135,10 +127,7 @@ public interface Nd4jArrayRing> : RingND, Nd4JArrayGroup> = - ThreadLocal.withInitial { hashMapOf() } - - private val longNd4jArrayRingCache: ThreadLocal> = - ThreadLocal.withInitial { hashMapOf() } + ThreadLocal.withInitial(::HashMap) /** * Creates an [RingND] for [Int] values or pull it from cache if it was created previously. @@ -146,20 +135,13 @@ public interface Nd4jArrayRing> : RingND, Nd4JArrayGroup = intNd4jArrayRingCache.get().getOrPut(shape) { IntNd4jArrayRing(shape) } - /** - * Creates an [RingND] for [Long] values or pull it from cache if it was created previously. - */ - public fun long(vararg shape: Int): Nd4jArrayRing = - longNd4jArrayRingCache.get().getOrPut(shape) { LongNd4jArrayRing(shape) } - /** * Creates a most suitable implementation of [RingND] using reified class. */ @Suppress("UNCHECKED_CAST") - public inline fun auto(vararg shape: Int): Nd4jArrayRing> = when { - T::class == Int::class -> int(*shape) as Nd4jArrayRing> - T::class == Long::class -> long(*shape) as Nd4jArrayRing> - else -> throw UnsupportedOperationException("This factory method only supports Int and Long types.") + public inline fun auto(vararg shape: Int): Nd4jArrayRing> = when { + T::class == Int::class -> int(*shape) as Nd4jArrayRing> + else -> throw UnsupportedOperationException("This factory method only supports Long type.") } } } @@ -168,11 +150,9 @@ public interface Nd4jArrayRing> : RingND, Nd4JArrayGroup> : FieldND, Nd4jArrayRing { - +public sealed interface Nd4jArrayField> : FieldND, Nd4jArrayRing { public override fun divide(a: StructureND, b: StructureND): Nd4jArrayStructure = a.ndArray.div(b.ndArray).wrap() @@ -180,10 +160,10 @@ public interface Nd4jArrayField> : FieldND, Nd4jArrayRing< public companion object { private val floatNd4jArrayFieldCache: ThreadLocal> = - ThreadLocal.withInitial { hashMapOf() } + ThreadLocal.withInitial(::HashMap) private val doubleNd4JArrayFieldCache: ThreadLocal> = - ThreadLocal.withInitial { hashMapOf() } + ThreadLocal.withInitial(::HashMap) /** * Creates an [FieldND] for [Float] values or pull it from cache if it was created previously. @@ -198,26 +178,64 @@ public interface Nd4jArrayField> : FieldND, Nd4jArrayRing< doubleNd4JArrayFieldCache.get().getOrPut(shape) { DoubleNd4jArrayField(shape) } /** - * Creates a most suitable implementation of [RingND] using reified class. + * Creates a most suitable implementation of [FieldND] using reified class. */ @Suppress("UNCHECKED_CAST") - public inline fun auto(vararg shape: Int): Nd4jArrayField> = when { - T::class == Float::class -> float(*shape) as Nd4jArrayField> - T::class == Double::class -> real(*shape) as Nd4jArrayField> + public inline fun auto(vararg shape: Int): Nd4jArrayField> = when { + T::class == Float::class -> float(*shape) as Nd4jArrayField> + T::class == Double::class -> real(*shape) as Nd4jArrayField> else -> throw UnsupportedOperationException("This factory method only supports Float and Double types.") } } } +/** + * Represents intersection of [ExtendedField] and [Field] over [Nd4jArrayStructure]. + */ +public sealed interface Nd4jArrayExtendedField> : ExtendedField>, + Nd4jArrayField { + public override fun sin(arg: StructureND): StructureND = Transforms.sin(arg.ndArray).wrap() + public override fun cos(arg: StructureND): StructureND = Transforms.cos(arg.ndArray).wrap() + public override fun asin(arg: StructureND): StructureND = Transforms.asin(arg.ndArray).wrap() + public override fun acos(arg: StructureND): StructureND = Transforms.acos(arg.ndArray).wrap() + public override fun atan(arg: StructureND): StructureND = Transforms.atan(arg.ndArray).wrap() + + public override fun power(arg: StructureND, pow: Number): StructureND = + Transforms.pow(arg.ndArray, pow).wrap() + + public override fun exp(arg: StructureND): StructureND = Transforms.exp(arg.ndArray).wrap() + public override fun ln(arg: StructureND): StructureND = Transforms.log(arg.ndArray).wrap() + public override fun sqrt(arg: StructureND): StructureND = Transforms.sqrt(arg.ndArray).wrap() + public override fun sinh(arg: StructureND): StructureND = Transforms.sinh(arg.ndArray).wrap() + public override fun cosh(arg: StructureND): StructureND = Transforms.cosh(arg.ndArray).wrap() + public override fun tanh(arg: StructureND): StructureND = Transforms.tanh(arg.ndArray).wrap() + + public override fun asinh(arg: StructureND): StructureND = + Nd4j.getExecutioner().exec(ASinh(arg.ndArray, arg.ndArray.ulike())).wrap() + + public override fun acosh(arg: StructureND): StructureND = + Nd4j.getExecutioner().exec(ACosh(arg.ndArray, arg.ndArray.ulike())).wrap() + + public override fun atanh(arg: StructureND): StructureND = Transforms.atanh(arg.ndArray).wrap() +} + /** * Represents [FieldND] over [Nd4jArrayDoubleStructure]. */ -public class DoubleNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField, - ExtendedField> { +public class DoubleNd4jArrayField(public override val shape: IntArray) : Nd4jArrayExtendedField { public override val elementContext: DoubleField get() = DoubleField public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asDoubleStructure() + @OptIn(PerformancePitfall::class) + override val StructureND.ndArray: INDArray + get() = when (this) { + is Nd4jArrayStructure -> checkShape(ndArray) + else -> Nd4j.zeros(*shape).also { + elements().forEach { (idx, value) -> it.putScalar(idx, value) } + } + } + override fun scale(a: StructureND, value: Double): Nd4jArrayStructure { return a.ndArray.mul(value).wrap() } @@ -245,34 +263,25 @@ public class DoubleNd4jArrayField(public override val shape: IntArray) : Nd4jArr public override operator fun Double.minus(arg: StructureND): Nd4jArrayStructure { return arg.ndArray.rsub(this).wrap() } - - override fun sin(arg: StructureND): StructureND = Transforms.sin(arg.ndArray).wrap() - - override fun cos(arg: StructureND): StructureND = Transforms.cos(arg.ndArray).wrap() - - override fun asin(arg: StructureND): StructureND = Transforms.asin(arg.ndArray).wrap() - - override fun acos(arg: StructureND): StructureND = Transforms.acos(arg.ndArray).wrap() - - override fun atan(arg: StructureND): StructureND = Transforms.atan(arg.ndArray).wrap() - - override fun power(arg: StructureND, pow: Number): StructureND = - Transforms.pow(arg.ndArray,pow).wrap() - - override fun exp(arg: StructureND): StructureND = Transforms.exp(arg.ndArray).wrap() - - override fun ln(arg: StructureND): StructureND = Transforms.log(arg.ndArray).wrap() } /** * Represents [FieldND] over [Nd4jArrayStructure] of [Float]. */ -public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArrayField, - ExtendedField> { +public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArrayExtendedField { public override val elementContext: FloatField get() = FloatField public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asFloatStructure() + @OptIn(PerformancePitfall::class) + public override val StructureND.ndArray: INDArray + get() = when (this) { + is Nd4jArrayStructure -> checkShape(ndArray) + else -> Nd4j.zeros(*shape).also { + elements().forEach { (idx, value) -> it.putScalar(idx, value) } + } + } + override fun scale(a: StructureND, value: Double): StructureND = a.ndArray.mul(value).wrap() @@ -293,23 +302,6 @@ public class FloatNd4jArrayField(public override val shape: IntArray) : Nd4jArra public override operator fun Float.minus(arg: StructureND): Nd4jArrayStructure = arg.ndArray.rsub(this).wrap() - - override fun sin(arg: StructureND): StructureND = Sin(arg.ndArray).z().wrap() - - override fun cos(arg: StructureND): StructureND = Cos(arg.ndArray).z().wrap() - - override fun asin(arg: StructureND): StructureND = ASin(arg.ndArray).z().wrap() - - override fun acos(arg: StructureND): StructureND = ACos(arg.ndArray).z().wrap() - - override fun atan(arg: StructureND): StructureND = ATan(arg.ndArray).z().wrap() - - override fun power(arg: StructureND, pow: Number): StructureND = - Pow(arg.ndArray, pow.toDouble()).z().wrap() - - override fun exp(arg: StructureND): StructureND = Exp(arg.ndArray).z().wrap() - - override fun ln(arg: StructureND): StructureND = Log(arg.ndArray).z().wrap() } /** @@ -321,6 +313,15 @@ public class IntNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRi public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asIntStructure() + @OptIn(PerformancePitfall::class) + public override val StructureND.ndArray: INDArray + get() = when (this) { + is Nd4jArrayStructure -> checkShape(ndArray) + else -> Nd4j.zeros(*shape).also { + elements().forEach { (idx, value) -> it.putScalar(idx, value) } + } + } + public override operator fun StructureND.plus(arg: Int): Nd4jArrayStructure = ndArray.add(arg).wrap() @@ -333,25 +334,3 @@ public class IntNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRi public override operator fun Int.minus(arg: StructureND): Nd4jArrayStructure = arg.ndArray.rsub(this).wrap() } - -/** - * Represents [RingND] over [Nd4jArrayStructure] of [Long]. - */ -public class LongNd4jArrayRing(public override val shape: IntArray) : Nd4jArrayRing { - public override val elementContext: LongRing - get() = LongRing - - public override fun INDArray.wrap(): Nd4jArrayStructure = checkShape(this).asLongStructure() - - public override operator fun StructureND.plus(arg: Long): Nd4jArrayStructure = - ndArray.add(arg).wrap() - - public override operator fun StructureND.minus(arg: Long): Nd4jArrayStructure = - ndArray.sub(arg).wrap() - - public override operator fun StructureND.times(arg: Long): Nd4jArrayStructure = - ndArray.mul(arg).wrap() - - public override operator fun Long.minus(arg: StructureND): Nd4jArrayStructure = - arg.ndArray.rsub(this).wrap() -} diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt index 71887ca3c..140a212f8 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt @@ -48,12 +48,6 @@ private class Nd4jArrayDoubleIterator(iterateOver: INDArray) : Nd4jArrayIterator internal fun INDArray.realIterator(): Iterator> = Nd4jArrayDoubleIterator(this) -private class Nd4jArrayLongIterator(iterateOver: INDArray) : Nd4jArrayIteratorBase(iterateOver) { - override fun getSingle(indices: LongArray) = iterateOver.getLong(*indices) -} - -internal fun INDArray.longIterator(): Iterator> = Nd4jArrayLongIterator(this) - private class Nd4jArrayIntIterator(iterateOver: INDArray) : Nd4jArrayIteratorBase(iterateOver) { override fun getSingle(indices: LongArray) = iterateOver.getInt(*indices.toIntArray()) } diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt index d37c91cb6..ffddcef90 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt @@ -17,7 +17,8 @@ import space.kscience.kmath.nd.StructureND */ public sealed class Nd4jArrayStructure : MutableStructureND { /** - * The wrapped [INDArray]. + * The wrapped [INDArray]. Since KMath uses [Int] indexes, assuming that the size of [INDArray] is less or equal to + * [Int.MAX_VALUE]. */ public abstract val ndArray: INDArray @@ -25,6 +26,7 @@ public sealed class Nd4jArrayStructure : MutableStructureND { internal abstract fun elementsIterator(): Iterator> internal fun indicesIterator(): Iterator = ndArray.indicesIterator() + @PerformancePitfall public override fun elements(): Sequence> = Sequence(::elementsIterator) } @@ -40,17 +42,6 @@ private data class Nd4jArrayIntStructure(override val ndArray: INDArray) : Nd4jA */ public fun INDArray.asIntStructure(): Nd4jArrayStructure = Nd4jArrayIntStructure(this) -private data class Nd4jArrayLongStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { - override fun elementsIterator(): Iterator> = ndArray.longIterator() - override fun get(index: IntArray): Long = ndArray.getLong(*index.toLongArray()) - override fun set(index: IntArray, value: Long): Unit = run { ndArray.putScalar(index, value.toDouble()) } -} - -/** - * Wraps this [INDArray] to [Nd4jArrayStructure]. - */ -public fun INDArray.asLongStructure(): Nd4jArrayStructure = Nd4jArrayLongStructure(this) - private data class Nd4jArrayDoubleStructure(override val ndArray: INDArray) : Nd4jArrayStructure() { override fun elementsIterator(): Iterator> = ndArray.realIterator() override fun get(index: IntArray): Double = ndArray.getDouble(*index) diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt new file mode 100644 index 000000000..456f7c2a9 --- /dev/null +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt @@ -0,0 +1,175 @@ +/* + * 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.nd4j + +import org.nd4j.linalg.api.ndarray.INDArray +import org.nd4j.linalg.api.ops.impl.summarystats.Variance +import org.nd4j.linalg.api.ops.impl.transforms.strict.ACosh +import org.nd4j.linalg.api.ops.impl.transforms.strict.ASinh +import org.nd4j.linalg.factory.Nd4j +import org.nd4j.linalg.factory.ops.NDBase +import org.nd4j.linalg.ops.transforms.Transforms +import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra +import space.kscience.kmath.tensors.api.Tensor +import space.kscience.kmath.tensors.api.TensorAlgebra +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra + +/** + * ND4J based [TensorAlgebra] implementation. + */ +public sealed interface Nd4jTensorAlgebra : AnalyticTensorAlgebra { + /** + * Wraps [INDArray] to [Nd4jArrayStructure]. + */ + public fun INDArray.wrap(): Nd4jArrayStructure + + /** + * Unwraps to or acquires [INDArray] from [StructureND]. + */ + public val StructureND.ndArray: INDArray + + public override fun T.plus(other: Tensor): Tensor = other.ndArray.add(this).wrap() + public override fun Tensor.plus(value: T): Tensor = ndArray.add(value).wrap() + + public override fun Tensor.plus(other: Tensor): Tensor = ndArray.add(other.ndArray).wrap() + + public override fun Tensor.plusAssign(value: T) { + ndArray.addi(value) + } + + public override fun Tensor.plusAssign(other: Tensor) { + ndArray.addi(other.ndArray) + } + + public override fun T.minus(other: Tensor): Tensor = other.ndArray.rsub(this).wrap() + public override fun Tensor.minus(value: T): Tensor = ndArray.sub(value).wrap() + public override fun Tensor.minus(other: Tensor): Tensor = ndArray.sub(other.ndArray).wrap() + + public override fun Tensor.minusAssign(value: T) { + ndArray.rsubi(value) + } + + public override fun Tensor.minusAssign(other: Tensor) { + ndArray.subi(other.ndArray) + } + + public override fun T.times(other: Tensor): Tensor = other.ndArray.mul(this).wrap() + + public override fun Tensor.times(value: T): Tensor = + ndArray.mul(value).wrap() + + public override fun Tensor.times(other: Tensor): Tensor = ndArray.mul(other.ndArray).wrap() + + public override fun Tensor.timesAssign(value: T) { + ndArray.muli(value) + } + + public override fun Tensor.timesAssign(other: Tensor) { + ndArray.mmuli(other.ndArray) + } + + public override fun Tensor.unaryMinus(): Tensor = ndArray.neg().wrap() + public override fun Tensor.get(i: Int): Tensor = ndArray.slice(i.toLong()).wrap() + public override fun Tensor.transpose(i: Int, j: Int): Tensor = ndArray.swapAxes(i, j).wrap() + public override fun Tensor.dot(other: Tensor): Tensor = ndArray.mmul(other.ndArray).wrap() + + public override fun Tensor.min(dim: Int, keepDim: Boolean): Tensor = + ndArray.min(keepDim, dim).wrap() + + public override fun Tensor.sum(dim: Int, keepDim: Boolean): Tensor = + ndArray.sum(keepDim, dim).wrap() + + public override fun Tensor.max(dim: Int, keepDim: Boolean): Tensor = + ndArray.max(keepDim, dim).wrap() + + public override fun Tensor.view(shape: IntArray): Tensor = ndArray.reshape(shape).wrap() + public override fun Tensor.viewAs(other: Tensor): Tensor = view(other.shape) + + public override fun Tensor.argMax(dim: Int, keepDim: Boolean): Tensor = + ndBase.get().argmax(ndArray, keepDim, dim).wrap() + + public override fun Tensor.mean(dim: Int, keepDim: Boolean): Tensor = ndArray.mean(keepDim, dim).wrap() + + public override fun Tensor.exp(): Tensor = Transforms.exp(ndArray).wrap() + public override fun Tensor.ln(): Tensor = Transforms.log(ndArray).wrap() + public override fun Tensor.sqrt(): Tensor = Transforms.sqrt(ndArray).wrap() + public override fun Tensor.cos(): Tensor = Transforms.cos(ndArray).wrap() + public override fun Tensor.acos(): Tensor = Transforms.acos(ndArray).wrap() + public override fun Tensor.cosh(): Tensor = Transforms.cosh(ndArray).wrap() + + public override fun Tensor.acosh(): Tensor = + Nd4j.getExecutioner().exec(ACosh(ndArray, ndArray.ulike())).wrap() + + public override fun Tensor.sin(): Tensor = Transforms.sin(ndArray).wrap() + public override fun Tensor.asin(): Tensor = Transforms.asin(ndArray).wrap() + public override fun Tensor.sinh(): Tensor = Transforms.sinh(ndArray).wrap() + + public override fun Tensor.asinh(): Tensor = + Nd4j.getExecutioner().exec(ASinh(ndArray, ndArray.ulike())).wrap() + + public override fun Tensor.tan(): Tensor = Transforms.tan(ndArray).wrap() + public override fun Tensor.atan(): Tensor = Transforms.atan(ndArray).wrap() + public override fun Tensor.tanh(): Tensor = Transforms.tanh(ndArray).wrap() + public override fun Tensor.atanh(): Tensor = Transforms.atanh(ndArray).wrap() + public override fun Tensor.ceil(): Tensor = Transforms.ceil(ndArray).wrap() + public override fun Tensor.floor(): Tensor = Transforms.floor(ndArray).wrap() + public override fun Tensor.std(dim: Int, keepDim: Boolean): Tensor = ndArray.std(true, keepDim, dim).wrap() + public override fun T.div(other: Tensor): Tensor = other.ndArray.rdiv(this).wrap() + public override fun Tensor.div(value: T): Tensor = ndArray.div(value).wrap() + public override fun Tensor.div(other: Tensor): Tensor = ndArray.div(other.ndArray).wrap() + + public override fun Tensor.divAssign(value: T) { + ndArray.divi(value) + } + + public override fun Tensor.divAssign(other: Tensor) { + ndArray.divi(other.ndArray) + } + + public override fun Tensor.variance(dim: Int, keepDim: Boolean): Tensor = + Nd4j.getExecutioner().exec(Variance(ndArray, true, true, dim)).wrap() + + private companion object { + private val ndBase: ThreadLocal = ThreadLocal.withInitial(::NDBase) + } +} + +/** + * [Double] specialization of [Nd4jTensorAlgebra]. + */ +public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra { + public override fun INDArray.wrap(): Nd4jArrayStructure = asDoubleStructure() + + @OptIn(PerformancePitfall::class) + public override val StructureND.ndArray: INDArray + get() = when (this) { + is Nd4jArrayStructure -> ndArray + else -> Nd4j.zeros(*shape).also { + elements().forEach { (idx, value) -> it.putScalar(idx, value) } + } + } + + public override fun Tensor.valueOrNull(): Double? = + if (shape contentEquals intArrayOf(1)) ndArray.getDouble(0) else null + + // TODO rewrite + @PerformancePitfall + public override fun diagonalEmbedding( + diagonalEntries: Tensor, + offset: Int, + dim1: Int, + dim2: Int, + ): Tensor = DoubleTensorAlgebra.diagonalEmbedding(diagonalEntries, offset, dim1, dim2) + + public override fun Tensor.sum(): Double = ndArray.sumNumber().toDouble() + public override fun Tensor.min(): Double = ndArray.minNumber().toDouble() + public override fun Tensor.max(): Double = ndArray.maxNumber().toDouble() + public override fun Tensor.mean(): Double = ndArray.meanNumber().toDouble() + public override fun Tensor.std(): Double = ndArray.stdNumber().toDouble() + public override fun Tensor.variance(): Double = ndArray.varNumber().toDouble() +} diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt index 6c414cc13..75a334ca7 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt @@ -5,5 +5,4 @@ package space.kscience.kmath.nd4j -internal fun IntArray.toLongArray(): LongArray = LongArray(size) { this[it].toLong() } internal fun LongArray.toIntArray(): IntArray = IntArray(size) { this[it].toInt() } diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt index c80a1d771..40da22763 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt @@ -52,7 +52,7 @@ internal class Nd4jArrayAlgebraTest { @Test fun testSin() = DoubleNd4jArrayField(intArrayOf(2, 2)).invoke { - val initial = produce { (i, j) -> if (i == j) PI/2 else 0.0 } + val initial = produce { (i, j) -> if (i == j) PI / 2 else 0.0 } val transformed = sin(initial) val expected = produce { (i, j) -> if (i == j) 1.0 else 0.0 } diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt index bdfec2ba6..30d01338f 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt @@ -72,7 +72,7 @@ internal class Nd4jArrayStructureTest { @Test fun testSet() { val nd = Nd4j.rand(17, 12, 4, 8)!! - val struct = nd.asLongStructure() + val struct = nd.asIntStructure() struct[intArrayOf(1, 2, 3, 4)] = 777 assertEquals(777, struct[1, 2, 3, 4]) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 2eb18ada6..62b8ef046 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -13,7 +13,7 @@ import space.kscience.kmath.operations.Algebra * * @param T the type of items in the tensors. */ -public interface TensorAlgebra: Algebra> { +public interface TensorAlgebra : Algebra> { /** * Returns a single tensor value of unit dimension if tensor shape equals to [1]. @@ -27,7 +27,8 @@ public interface TensorAlgebra: Algebra> { * * @return the value of a scalar tensor. */ - public fun Tensor.value(): T + public fun Tensor.value(): T = + valueOrNull() ?: throw IllegalArgumentException("Inconsistent value for tensor of with $shape shape") /** * Each element of the tensor [other] is added to this value. @@ -60,15 +61,14 @@ public interface TensorAlgebra: Algebra> { * * @param value the number to be added to each element of this tensor. */ - public operator fun Tensor.plusAssign(value: T): Unit + public operator fun Tensor.plusAssign(value: T) /** * Each element of the tensor [other] is added to each element of this tensor. * * @param other tensor to be added. */ - public operator fun Tensor.plusAssign(other: Tensor): Unit - + public operator fun Tensor.plusAssign(other: Tensor) /** * Each element of the tensor [other] is subtracted from this value. @@ -101,14 +101,14 @@ public interface TensorAlgebra: Algebra> { * * @param value the number to be subtracted from each element of this tensor. */ - public operator fun Tensor.minusAssign(value: T): Unit + public operator fun Tensor.minusAssign(value: T) /** * Each element of the tensor [other] is subtracted from each element of this tensor. * * @param other tensor to be subtracted. */ - public operator fun Tensor.minusAssign(other: Tensor): Unit + public operator fun Tensor.minusAssign(other: Tensor) /** @@ -142,14 +142,14 @@ public interface TensorAlgebra: Algebra> { * * @param value the number to be multiplied by each element of this tensor. */ - public operator fun Tensor.timesAssign(value: T): Unit + public operator fun Tensor.timesAssign(value: T) /** * Each element of the tensor [other] is multiplied by each element of this tensor. * * @param other tensor to be multiplied. */ - public operator fun Tensor.timesAssign(other: Tensor): Unit + public operator fun Tensor.timesAssign(other: Tensor) /** * Numerical negative, element-wise. @@ -217,7 +217,7 @@ public interface TensorAlgebra: Algebra> { * a 1 is prepended to its dimension for the purpose of the batched matrix multiply and removed after. * If the second argument is 1-dimensional, a 1 is appended to its dimension for the purpose of the batched matrix * multiple and removed after. - * The non-matrix (i.e. batch) dimensions are broadcasted (and thus must be broadcastable). + * The non-matrix (i.e. batch) dimensions are broadcast (and thus must be broadcastable). * For example, if `input` is a (j × 1 × n × n) tensor and `other` is a * (k × n × n) tensor, out will be a (j × k × n × n) tensor. * @@ -255,7 +255,7 @@ public interface TensorAlgebra: Algebra> { diagonalEntries: Tensor, offset: Int = 0, dim1: Int = -2, - dim2: Int = -1 + dim2: Int = -1, ): Tensor /** diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 78989f1f3..1fd46bd57 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -9,20 +9,9 @@ import space.kscience.kmath.nd.as1D import space.kscience.kmath.nd.as2D import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra -import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.internal.dotHelper -import space.kscience.kmath.tensors.core.internal.getRandomNormals +import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra import space.kscience.kmath.tensors.core.internal.* -import space.kscience.kmath.tensors.core.internal.broadcastOuterTensors -import space.kscience.kmath.tensors.core.internal.checkBufferShapeConsistency -import space.kscience.kmath.tensors.core.internal.checkEmptyDoubleBuffer -import space.kscience.kmath.tensors.core.internal.checkEmptyShape -import space.kscience.kmath.tensors.core.internal.checkShapesCompatible -import space.kscience.kmath.tensors.core.internal.checkSquareMatrix -import space.kscience.kmath.tensors.core.internal.checkTranspose -import space.kscience.kmath.tensors.core.internal.checkView -import space.kscience.kmath.tensors.core.internal.minusIndexFrom import kotlin.math.* /** @@ -38,8 +27,8 @@ public open class DoubleTensorAlgebra : override fun Tensor.valueOrNull(): Double? = if (tensor.shape contentEquals intArrayOf(1)) tensor.mutableBuffer.array()[tensor.bufferStart] else null - override fun Tensor.value(): Double = - valueOrNull() ?: throw IllegalArgumentException("Inconsistent value for tensor of with $shape shape") + override fun Tensor.value(): Double = valueOrNull() + ?: throw IllegalArgumentException("The tensor shape is $shape, but value method is allowed only for shape [1]") /** * Constructs a tensor with the specified shape and data. @@ -466,7 +455,7 @@ public open class DoubleTensorAlgebra : private fun Tensor.eq( other: Tensor, - eqFunction: (Double, Double) -> Boolean + eqFunction: (Double, Double) -> Boolean, ): Boolean { checkShapesCompatible(tensor, other) val n = tensor.numElements @@ -540,7 +529,7 @@ public open class DoubleTensorAlgebra : internal fun Tensor.foldDim( foldFunction: (DoubleArray) -> Double, dim: Int, - keepDim: Boolean + keepDim: Boolean, ): DoubleTensor { check(dim < dimension) { "Dimension $dim out of range $dimension" } val resShape = if (keepDim) { @@ -729,7 +718,7 @@ public open class DoubleTensorAlgebra : */ public fun luPivot( luTensor: Tensor, - pivotsTensor: Tensor + pivotsTensor: Tensor, ): Triple { checkSquareMatrix(luTensor.shape) check( From 485e90fcd0f3e66ea5a1566634041117b983ae84 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 20 May 2021 23:32:56 +0700 Subject: [PATCH 366/393] Rename DifferentiableMstExpression, fix #349 --- CHANGELOG.md | 1 + build.gradle.kts | 1 + kmath-kotlingrad/build.gradle.kts | 6 ++++-- ...tExpression.kt => KotlingradExpression.kt} | 20 +++++++++---------- ...{ScalarsAdapters.kt => scalarsAdapters.kt} | 12 ++++++++--- kmath-nd4j/build.gradle.kts | 3 ++- 6 files changed, 27 insertions(+), 16 deletions(-) rename kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/{DifferentiableMstExpression.kt => KotlingradExpression.kt} (68%) rename kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/{ScalarsAdapters.kt => scalarsAdapters.kt} (84%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 274a403b1..9c6b14b95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ - Replace `MST.Symbolic` by `Symbol`, `Symbol` now implements MST - Remove Any restriction on polynomials - Add `out` variance to type parameters of `StructureND` and its implementations where possible +- Rename `DifferentiableMstExpression` to `KotlingradExpression` ### Deprecated diff --git a/build.gradle.kts b/build.gradle.kts index 93f5059ff..d44833445 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,6 +11,7 @@ allprojects { isAllowInsecureProtocol = true } maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven") + maven("https://oss.sonatype.org/content/repositories/snapshots") mavenCentral() } diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index 0e8e49971..01b42d7ba 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -3,14 +3,16 @@ plugins { id("ru.mipt.npm.gradle.common") } +description = "Kotlin∇ integration module" + dependencies { api("com.github.breandan:kaliningraph:0.1.6") api("com.github.breandan:kotlingrad:0.4.5") - api(project(":kmath-ast")) + api(project(":kmath-core")) + testImplementation(project(":kmath-ast")) } readme { - description = "Functions, integration and interpolation" maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt similarity index 68% rename from kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt rename to kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt index 59d481d02..72ecee4f1 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt @@ -11,24 +11,24 @@ import space.kscience.kmath.expressions.* import space.kscience.kmath.operations.NumericAlgebra /** - * Represents [MST] based [DifferentiableExpression]. + * Represents [MST] based [DifferentiableExpression] relying on [Kotlin∇](https://github.com/breandan/kotlingrad). * - * The principle of this API is converting the [mst] to an [SFun], differentiating it with - * [Kotlin∇](https://github.com/breandan/kotlingrad), then converting [SFun] back to [MST]. + * The principle of this API is converting the [mst] to an [SFun], differentiating it with Kotlin∇, then converting + * [SFun] back to [MST]. * * @param T The type of number. * @param A The [NumericAlgebra] of [T]. * @property algebra The [A] instance. * @property mst The [MST] node. */ -public class DifferentiableMstExpression>( +public class KotlingradExpression>( public val algebra: A, public val mst: MST, -) : DifferentiableExpression> { +) : DifferentiableExpression> { public override fun invoke(arguments: Map): T = mst.interpret(algebra, arguments) - public override fun derivativeOrNull(symbols: List): DifferentiableMstExpression = - DifferentiableMstExpression( + public override fun derivativeOrNull(symbols: List): KotlingradExpression = + KotlingradExpression( algebra, symbols.map(Symbol::identity) .map(MstNumericAlgebra::bindSymbol) @@ -39,7 +39,7 @@ public class DifferentiableMstExpression>( } /** - * Wraps this [MST] into [DifferentiableMstExpression]. + * Wraps this [MST] into [KotlingradExpression]. */ -public fun > MST.toDiffExpression(algebra: A): DifferentiableMstExpression = - DifferentiableMstExpression(algebra, this) +public fun > MST.toDiffExpression(algebra: A): KotlingradExpression = + KotlingradExpression(algebra, this) diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt similarity index 84% rename from kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt rename to kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt index 8e3c54035..6c0b98c59 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/ScalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt @@ -14,7 +14,7 @@ import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.operations.* /** - * Maps [SVar] to [MST.Symbolic] directly. + * Maps [SVar] to [Symbol] directly. * * @receiver The variable. * @returnAa node. @@ -81,7 +81,7 @@ public fun > SFun.toMst(): MST = MstExtendedField { public fun > MST.Numeric.toSConst(): SConst = SConst(value) /** - * Maps [MST.Symbolic] to [SVar] directly. + * Maps [Symbol] to [SVar] directly. * * @receiver The node. * @return A new variable. @@ -94,7 +94,7 @@ internal fun > Symbol.toSVar(): SVar = SVar(identity) * Detailed mapping is: * * - [MST.Numeric] -> [SConst]; - * - [MST.Symbolic] -> [SVar]; + * - [Symbol] -> [SVar]; * - [MST.Unary] -> [Negative], [Sine], [Cosine], [Tangent], [Power], [Log]; * - [MST.Binary] -> [Sum], [Prod], [Power]. * @@ -114,6 +114,12 @@ public fun > MST.toSFun(): SFun = when (this) { PowerOperations.SQRT_OPERATION -> sqrt(value.toSFun()) ExponentialOperations.EXP_OPERATION -> exp(value.toSFun()) ExponentialOperations.LN_OPERATION -> value.toSFun().ln() + ExponentialOperations.SINH_OPERATION -> MstExtendedField { (exp(value) - exp(-value)) / 2.0 }.toSFun() + ExponentialOperations.COSH_OPERATION -> MstExtendedField { (exp(value) + exp(-value)) / 2.0 }.toSFun() + ExponentialOperations.TANH_OPERATION -> MstExtendedField { (exp(value) - exp(-value)) / (exp(-value) + exp(value)) }.toSFun() + ExponentialOperations.ASINH_OPERATION -> MstExtendedField { ln(sqrt(value * value + one) + value) }.toSFun() + ExponentialOperations.ACOSH_OPERATION -> MstExtendedField { ln(value + sqrt((value - one) * (value + one))) }.toSFun() + ExponentialOperations.ATANH_OPERATION -> MstExtendedField { (ln(value + one) - ln(one - value)) / 2.0 }.toSFun() else -> error("Unary operation $operation not defined in $this") } diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 12ea5c130..abcc02962 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -3,6 +3,8 @@ plugins { id("ru.mipt.npm.gradle.common") } +description = "ND4J NDStructure implementation and according NDAlgebra classes" + dependencies { api(project(":kmath-tensors")) api("org.nd4j:nd4j-api:1.0.0-beta7") @@ -12,7 +14,6 @@ dependencies { } readme { - description = "ND4J NDStructure implementation and according NDAlgebra classes" maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature(id = "nd4jarraystructure") { "NDStructure wrapper for INDArray" } From a722cf0cdb7810c5cf1bde7c076fcef28f0d7452 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 21 May 2021 15:47:35 +0700 Subject: [PATCH 367/393] Integration between MST and Symja IExpr --- CHANGELOG.md | 9 +- examples/build.gradle.kts | 2 +- .../kscience/kmath/ast/kotlingradSupport.kt | 20 ++-- .../space/kscience/kmath/ast/symjaSupport.kt | 27 ++++++ .../kmath/kotlingrad/KotlingradExpression.kt | 4 +- kmath-symja/build.gradle.kts | 21 ++++ .../kscience/kmath/symja/SymjaExpression.kt | 34 +++++++ .../space/kscience/kmath/symja/adapters.kt | 95 +++++++++++++++++++ settings.gradle.kts | 1 + 9 files changed, 195 insertions(+), 18 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt create mode 100644 kmath-symja/build.gradle.kts create mode 100644 kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt create mode 100644 kmath-symja/src/main/kotlin/space/kscience/kmath/symja/adapters.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c6b14b95..2ff5dd623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,18 +2,19 @@ ## [Unreleased] ### Added -- ScaleOperations interface -- Field extends ScaleOperations +- `ScaleOperations` interface +- `Field` extends `ScaleOperations` - Basic integration API - Basic MPP distributions and samplers -- bindSymbolOrNull +- `bindSymbolOrNull` - Blocking chains and Statistics - Multiplatform integration - Integration for any Field element - Extended operations for ND4J fields - Jupyter Notebook integration module (kmath-jupyter) - `@PerformancePitfall` annotation to mark possibly slow API -- BigInt operation performance improvement and fixes by @zhelenskiy (#328) +- `BigInt` operation performance improvement and fixes by @zhelenskiy (#328) +- Integration between `MST` and Symja `IExpr` ### Changed - Exponential operations merged with hyperbolic functions diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index d095db1ba..568bde153 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -26,7 +26,7 @@ dependencies { implementation(project(":kmath-ejml")) implementation(project(":kmath-nd4j")) implementation(project(":kmath-tensors")) - + implementation(project(":kmath-symja")) implementation(project(":kmath-for-real")) implementation("org.nd4j:nd4j-native:1.0.0-beta7") diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt index 420b23f9f..6ceaa962a 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt @@ -5,25 +5,23 @@ package space.kscience.kmath.ast -import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.expressions.derivative import space.kscience.kmath.expressions.invoke -import space.kscience.kmath.expressions.symbol -import space.kscience.kmath.kotlingrad.toDiffExpression +import space.kscience.kmath.expressions.Symbol.Companion.x +import space.kscience.kmath.expressions.toExpression +import space.kscience.kmath.kotlingrad.toKotlingradExpression import space.kscience.kmath.operations.DoubleField /** * In this example, x^2-4*x-44 function is differentiated with Kotlin∇, and the autodiff result is compared with - * valid derivative. + * valid derivative in a certain point. */ fun main() { - val x by symbol - - val actualDerivative = "x^2-4*x-44".parseMath() - .toDiffExpression(DoubleField) + val actualDerivative = "x^2-4*x-44" + .parseMath() + .toKotlingradExpression(DoubleField) .derivative(x) - - val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField) - assert(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0)) + val expectedDerivative = "2*x-4".parseMath().toExpression(DoubleField) + check(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0)) } diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt new file mode 100644 index 000000000..a9eca0500 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt @@ -0,0 +1,27 @@ +/* + * 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.ast + +import space.kscience.kmath.expressions.Symbol.Companion.x +import space.kscience.kmath.expressions.derivative +import space.kscience.kmath.expressions.invoke +import space.kscience.kmath.expressions.toExpression +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.symja.toSymjaExpression + +/** + * In this example, x^2-4*x-44 function is differentiated with Symja, and the autodiff result is compared with + * valid derivative in a certain point. + */ +fun main() { + val actualDerivative = "x^2-4*x-44" + .parseMath() + .toSymjaExpression(DoubleField) + .derivative(x) + + val expectedDerivative = "2*x-4".parseMath().toExpression(DoubleField) + check(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0)) +} diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt index 72ecee4f1..8312eaff3 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt @@ -39,7 +39,7 @@ public class KotlingradExpression>( } /** - * Wraps this [MST] into [KotlingradExpression]. + * Wraps this [MST] into [KotlingradExpression] in the context of [algebra]. */ -public fun > MST.toDiffExpression(algebra: A): KotlingradExpression = +public fun > MST.toKotlingradExpression(algebra: A): KotlingradExpression = KotlingradExpression(algebra, this) diff --git a/kmath-symja/build.gradle.kts b/kmath-symja/build.gradle.kts new file mode 100644 index 000000000..c06020bb6 --- /dev/null +++ b/kmath-symja/build.gradle.kts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +plugins { + kotlin("jvm") + id("ru.mipt.npm.gradle.common") +} + +description = "Symja integration module" + +dependencies { + api("org.matheclipse:matheclipse-core:2.0.0-SNAPSHOT") + api(project(":kmath-core")) + testImplementation("org.slf4j:slf4j-simple:1.7.30") +} + +readme { + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE +} diff --git a/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt new file mode 100644 index 000000000..301678916 --- /dev/null +++ b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt @@ -0,0 +1,34 @@ +/* + * 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.symja + +import org.matheclipse.core.eval.ExprEvaluator +import org.matheclipse.core.expression.F +import space.kscience.kmath.expressions.DifferentiableExpression +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.expressions.interpret +import space.kscience.kmath.operations.NumericAlgebra + +public class SymjaExpression>( + public val algebra: A, + public val mst: MST, + public val evaluator: ExprEvaluator = DEFAULT_EVALUATOR, +) : DifferentiableExpression> { + public override fun invoke(arguments: Map): T = mst.interpret(algebra, arguments) + + public override fun derivativeOrNull(symbols: List): SymjaExpression = SymjaExpression( + algebra, + symbols.map(Symbol::toIExpr).fold(mst.toIExpr(), F::D).toMst(evaluator), + evaluator, + ) +} + +/** + * Wraps this [MST] into [SymjaExpression] in the context of [algebra]. + */ +public fun > MST.toSymjaExpression(algebra: A): SymjaExpression = + SymjaExpression(algebra, this) diff --git a/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/adapters.kt b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/adapters.kt new file mode 100644 index 000000000..95dd1ebbf --- /dev/null +++ b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/adapters.kt @@ -0,0 +1,95 @@ +/* + * 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.symja + +import org.matheclipse.core.eval.ExprEvaluator +import org.matheclipse.core.expression.ComplexNum +import org.matheclipse.core.expression.F +import org.matheclipse.core.interfaces.IExpr +import org.matheclipse.core.interfaces.ISymbol +import space.kscience.kmath.expressions.MST +import space.kscience.kmath.expressions.MstExtendedField +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.operations.* + +internal val DEFAULT_EVALUATOR = ExprEvaluator(false, 100) + +/** + * Matches the given [IExpr] instance to appropriate [MST] node or evaluates it with [evaluator]. + */ +public fun IExpr.toMst(evaluator: ExprEvaluator = DEFAULT_EVALUATOR): MST = MstExtendedField { + when { + isPlus -> first().toMst(evaluator) + second().toMst(evaluator) + isSin -> sin(first().toMst(evaluator)) + isSinh -> sinh(first().toMst(evaluator)) + isCos -> cos(first().toMst(evaluator)) + isCosh -> cosh(first().toMst(evaluator)) + isTan -> tan(first().toMst(evaluator)) + isTanh -> tanh(first().toMst(evaluator)) + isArcSin -> asin(first().toMst(evaluator)) + isArcCos -> acos(first().toMst(evaluator)) + isArcTan -> atan(first().toMst(evaluator)) + isArcTanh -> atanh(first().toMst(evaluator)) + isE -> bindSymbol("e") + isPi -> bindSymbol("pi") + isTimes -> first().toMst(evaluator) * second().toMst(evaluator) + isOne -> one + isZero -> zero + isImaginaryUnit -> bindSymbol("i") + isMinusOne -> -one + this@toMst is ISymbol -> bindSymbol(symbolName) + isPower -> power(first().toMst(evaluator), evaluator.evalf(second())) + isExp -> exp(first().toMst(evaluator)) + isNumber -> number(evaluator.evalf(this@toMst)) + this@toMst === F.NIL -> error("NIL cannot be converted to MST") + else -> evaluator.eval(this@toMst.toString()).toMst(evaluator) + } +} + +/** + * Matches the given [MST] instance to appropriate [IExpr] node, only standard operations and symbols (which are + * present in, say, [MstExtendedField]) are supported. + */ +public fun MST.toIExpr(): IExpr = when (this) { + is MST.Numeric -> F.symjify(value) + + is Symbol -> when (identity) { + "e" -> F.E + "pi" -> F.Pi + "i" -> ComplexNum.I + else -> F.Dummy(identity) + } + + is MST.Unary -> when (operation) { + GroupOperations.PLUS_OPERATION -> value.toIExpr() + GroupOperations.MINUS_OPERATION -> F.Negate(value.toIExpr()) + TrigonometricOperations.SIN_OPERATION -> F.Sin(value.toIExpr()) + TrigonometricOperations.COS_OPERATION -> F.Cos(value.toIExpr()) + TrigonometricOperations.TAN_OPERATION -> F.Tan(value.toIExpr()) + TrigonometricOperations.ASIN_OPERATION -> F.ArcSin(value.toIExpr()) + TrigonometricOperations.ACOS_OPERATION -> F.ArcCos(value.toIExpr()) + TrigonometricOperations.ATAN_OPERATION -> F.ArcTan(value.toIExpr()) + ExponentialOperations.SINH_OPERATION -> F.Sinh(value.toIExpr()) + ExponentialOperations.COSH_OPERATION -> F.Cosh(value.toIExpr()) + ExponentialOperations.TANH_OPERATION -> F.Tanh(value.toIExpr()) + ExponentialOperations.ASINH_OPERATION -> F.ArcSinh(value.toIExpr()) + ExponentialOperations.ACOSH_OPERATION -> F.ArcCosh(value.toIExpr()) + ExponentialOperations.ATANH_OPERATION -> F.ArcTanh(value.toIExpr()) + PowerOperations.SQRT_OPERATION -> F.Sqrt(value.toIExpr()) + ExponentialOperations.EXP_OPERATION -> F.Exp(value.toIExpr()) + ExponentialOperations.LN_OPERATION -> F.Log(value.toIExpr()) + else -> error("Unary operation $operation not defined in $this") + } + + is MST.Binary -> when (operation) { + GroupOperations.PLUS_OPERATION -> left.toIExpr() + right.toIExpr() + GroupOperations.MINUS_OPERATION -> left.toIExpr() - right.toIExpr() + RingOperations.TIMES_OPERATION -> left.toIExpr() * right.toIExpr() + FieldOperations.DIV_OPERATION -> F.Divide(left.toIExpr(), right.toIExpr()) + PowerOperations.POW_OPERATION -> F.Power(left.toIExpr(), F.symjify((right as MST.Numeric).value)) + else -> error("Binary operation $operation not defined in $this") + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index cc9eb4860..d47aea2a7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -42,6 +42,7 @@ include( ":kmath-kotlingrad", ":kmath-tensors", ":kmath-jupyter", + ":kmath-symja", ":examples", ":benchmarks" ) From 189449f40e2d84c314225f92cec3cf04c4565aa8 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Fri, 21 May 2021 20:08:17 +0700 Subject: [PATCH 368/393] Fix unresolved reference in generated type parameter --- .../space/kscience/kmath/asm/internal/AsmBuilder.kt | 4 ++-- .../kotlin/space/kscience/kmath/expressions/Symbol.kt | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt index 39ebf049d..a796ae2a5 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt @@ -342,8 +342,8 @@ internal class AsmBuilder( val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("space/kscience/kmath/asm/internal/MapIntrinsics") } /** - * ASM Type for [space.kscience.kmath.misc.Symbol]. + * ASM Type for [space.kscience.kmath.expressions.Symbol]. */ - val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/misc/Symbol") } + val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Symbol") } } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt index 10a9ca5a1..74dc7aedc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt @@ -12,13 +12,13 @@ import kotlin.properties.ReadOnlyProperty * A marker interface for a symbol. A symbol must have an identity. * Ic */ -public interface Symbol: MST { +public interface Symbol : MST { /** * Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol. */ public val identity: String - public companion object{ + public companion object { public val x: StringSymbol = StringSymbol("x") public val y: StringSymbol = StringSymbol("y") public val z: StringSymbol = StringSymbol("z") @@ -48,7 +48,7 @@ public operator fun Map.get(symbol: Symbol): T? = get(symbol.iden /** * Set a value of [String]-keyed map by a [Symbol] */ -public operator fun MutableMap.set(symbol: Symbol, value: T){ +public operator fun MutableMap.set(symbol: Symbol, value: T) { set(symbol.identity, value) } @@ -60,6 +60,6 @@ public operator fun Map.get(string: String): T? = get(StringSymbo /** * Set a value of [String]-keyed map by a [Symbol] */ -public operator fun MutableMap.set(string: String, value: T){ +public operator fun MutableMap.set(string: String, value: T) { set(StringSymbol(string), value) } \ No newline at end of file From 18509f1259ca5363ce3059e68bcc69a85f94c429 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 21 May 2021 23:14:07 +0300 Subject: [PATCH 369/393] Simpson integrator --- .../kscience/kmath/functions/interpolate.kt | 1 - ...Integrator.kt => CMGaussRuleIntegrator.kt} | 4 +- .../kmath/integration/SimpsonIntegrator.kt | 36 +++++++++++++++--- .../kmath/integration/SplineIntegrator.kt | 12 ++++++ .../kmath/integration/UnivariateIntegrand.kt | 2 +- .../kmath/integration/GaussIntegralTest.kt | 4 +- .../kmath/integration/SimpsonIntegralTest.kt | 38 +++++++++++++++++++ 7 files changed, 85 insertions(+), 12 deletions(-) rename kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/{GaussRuleIntegrator.kt => CMGaussRuleIntegrator.kt} (96%) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt index b05c003a6..8dbc7b7a4 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt @@ -35,7 +35,6 @@ fun main() { data.map { it.second }.toDoubleArray() ) - Plotly.plot { scatter { name = "interpolated" diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt similarity index 96% rename from kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt rename to kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt index 304fdec8f..4e174723d 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/GaussRuleIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt @@ -11,7 +11,7 @@ import space.kscience.kmath.integration.* /** * A simple one-pass integrator based on Gauss rule */ -public class GaussRuleIntegrator( +public class CMGaussRuleIntegrator( private val numpoints: Int, private var type: GaussRule = GaussRule.LEGANDRE, ) : UnivariateIntegrator { @@ -76,7 +76,7 @@ public class GaussRuleIntegrator( numPoints: Int = 100, type: GaussRule = GaussRule.LEGANDRE, function: (Double) -> Double, - ): Double = GaussRuleIntegrator(numPoints, type).integrate( + ): Double = CMGaussRuleIntegrator(numPoints, type).integrate( UnivariateIntegrand(function, IntegrationRange(range)) ).valueOrNull!! } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt index 526d4d35d..7eca90f88 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt @@ -5,13 +5,37 @@ package space.kscience.kmath.integration -import space.kscience.kmath.operations.Ring - +import space.kscience.kmath.operations.Field +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferFactory +/** + * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. + * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 10 points. + */ public class SimpsonIntegrator( - public val algebra: Ring, + public val algebra: Field, + public val bufferFactory: BufferFactory, ) : UnivariateIntegrator { - override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand { - TODO("Not yet implemented") + override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand = with(algebra) { + val numPoints = integrand.getFeature()?.maxCalls ?: 100 + require(numPoints >= 4) + val range = integrand.getFeature()?.range ?: 0.0..1.0 + val h: Double = (range.endInclusive - range.start) / (numPoints - 1) + val points: Buffer = bufferFactory(numPoints) { i -> + integrand.function(range.start + i * h) + }// equally distributed point + + fun simpson(index: Int) = h / 3 * (points[index - 1] + 4 * points[index] + points[index + 1]) + var res = zero + res += simpson(1) / 1.5 //border points with 1.5 factor + for (i in 2 until (points.size - 2)) { + res += simpson(i) / 2 + } + res += simpson(points.size - 2) / 1.5 //border points with 1.5 factor + return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + points.size) } -} \ No newline at end of file +} + +public inline val Field.simpsonIntegrator: SimpsonIntegrator + get() = SimpsonIntegrator(this, Buffer.Companion::auto) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt new file mode 100644 index 000000000..da5730497 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt @@ -0,0 +1,12 @@ +/* + * 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.integration + +public class SplineIntegrator: UnivariateIntegrator { + override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index c03cc8df0..d3d0220f6 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI import kotlin.jvm.JvmInline import kotlin.reflect.KClass -public class UnivariateIntegrand internal constructor( +public class UnivariateIntegrand internal constructor( private val features: Map, IntegrandFeature>, public val function: (Double) -> T, ) : Integrand { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 5c9241120..9f48a15ea 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -19,7 +19,7 @@ class GaussIntegralTest { val res = DoubleField.gaussIntegrator.integrate(0.0..2 * PI) { x -> sin(x) } - assertEquals(0.0, res.valueOrNull!!, 1e-2) + assertEquals(0.0, res.value, 1e-2) } @Test @@ -31,7 +31,7 @@ class GaussIntegralTest { 0.0 } } - assertEquals(15.0, res.valueOrNull!!, 0.5) + assertEquals(15.0, res.value, 0.5) } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt new file mode 100644 index 000000000..b0c0cd098 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt @@ -0,0 +1,38 @@ +/* + * 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.integration + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.DoubleField +import kotlin.math.PI +import kotlin.math.sin +import kotlin.test.Test +import kotlin.test.assertEquals + +@OptIn(UnstableKMathAPI::class) +class SimpsonIntegralTest { + @Test + fun gaussSin() { + val res = DoubleField.simpsonIntegrator.integrate(0.0..2 * PI, IntegrandMaxCalls(5)) { x -> + sin(x) + } + assertEquals(0.0, res.value, 1e-2) + } + + @Test + fun gaussUniform() { + val res = DoubleField.simpsonIntegrator.integrate(35.0..100.0) { x -> + if(x in 30.0..50.0){ + 1.0 + } else { + 0.0 + } + } + assertEquals(15.0, res.value, 0.5) + } + + +} \ No newline at end of file From a24c8dcbce3256bb0f707fcf373cbaccbec1760a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 22 May 2021 20:08:49 +0300 Subject: [PATCH 370/393] Simpson and spline integration --- .../kmath/functions/interpolateSquare.kt | 45 +++++++++ .../kmath/operations/algebraExtensions.kt | 2 + .../kmath/structures/NumberNDFieldTest.kt | 4 +- .../kscience/kmath/functions/Polynomial.kt | 15 ++- .../kmath/integration/GaussIntegrator.kt | 8 +- .../kmath/integration/SimpsonIntegrator.kt | 45 ++++++--- .../kmath/integration/SplineIntegrator.kt | 98 ++++++++++++++++++- .../kmath/integration/UnivariateIntegrand.kt | 15 +++ .../kmath/interpolation/Interpolator.kt | 6 ++ .../kmath/integration/SimpsonIntegralTest.kt | 6 +- .../kmath/integration/SplineIntegralTest.kt | 48 +++++++++ settings.gradle.kts | 8 +- 12 files changed, 260 insertions(+), 40 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt new file mode 100644 index 000000000..33973c880 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt @@ -0,0 +1,45 @@ +/* + * 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.interpolation.SplineInterpolator +import space.kscience.kmath.interpolation.interpolatePolynomials +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.real.step +import space.kscience.kmath.structures.map +import space.kscience.plotly.Plotly +import space.kscience.plotly.UnstablePlotlyAPI +import space.kscience.plotly.makeFile +import space.kscience.plotly.models.functionXY +import space.kscience.plotly.scatter + +@OptIn(UnstablePlotlyAPI::class) +fun main() { + val function: UnivariateFunction = { x -> + if (x in 30.0..50.0) { + 1.0 + } else { + 0.0 + } + } + val xs = 0.0..100.0 step 0.5 + val ys = xs.map(function) + + val polynomial: PiecewisePolynomial = SplineInterpolator.double.interpolatePolynomials(xs, ys) + + val polyFunction = polynomial.asFunction(DoubleField, 0.0) + + Plotly.plot { + scatter { + name = "interpolated" + functionXY(25.0..55.0, 0.1) { polyFunction(it) } + } + scatter { + name = "original" + functionXY(25.0..55.0, 0.1) { function(it) } + } + }.makeFile() +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 7967aeadb..d52be943a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -16,6 +16,8 @@ public fun Ring.sum(data: Iterable): T = data.fold(zero) { left, right add(left, right) } +//TODO replace by sumOf with multi-receivers + /** * Returns the sum of all elements in the sequence in this [Ring]. * diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt index 57393fadd..fb51553f7 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt @@ -74,9 +74,9 @@ class NumberNDFieldTest { val division = array1.combine(array2, Double::div) } - object L2Norm : Norm, Double> { + object L2Norm : Norm, Double> { @OptIn(PerformancePitfall::class) - override fun norm(arg: StructureND): Double = + override fun norm(arg: StructureND): Double = kotlin.math.sqrt(arg.elements().sumOf { it.second.toDouble() }) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 4976befcb..ba77d7b25 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -69,18 +69,23 @@ public fun Polynomial.differentiate( public fun Polynomial.integrate( algebra: A, ): Polynomial where A : Field, A : NumericAlgebra = algebra { - Polynomial(coefficients.mapIndexed { index, t -> t / number(index) }) + val integratedCoefficients = buildList(coefficients.size + 1) { + add(zero) + coefficients.forEachIndexed{ index, t -> add(t / (number(index) + one)) } + } + Polynomial(integratedCoefficients) } /** * Compute a definite integral of a given polynomial in a [range] */ @UnstableKMathAPI -public fun , A> Polynomial.integrate( - algebra: A, +public fun > Polynomial.integrate( + algebra: Field, range: ClosedRange, -): T where A : Field, A : NumericAlgebra = algebra { - value(algebra, range.endInclusive) - value(algebra, range.start) +): T = algebra { + val integral = integrate(algebra) + integral.value(algebra, range.endInclusive) - integral.value(algebra, range.start) } /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index 26757ae68..283f97557 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -10,13 +10,7 @@ import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.structures.indices -/** - * Set of univariate integration ranges. First components correspond to ranges themselves, second components to number of - * integration nodes per range - */ -public class UnivariateIntegrandRanges(public val ranges: List, Int>>) : IntegrandFeature { - public constructor(vararg pairs: Pair, Int>) : this(pairs.toList()) -} + /** * A simple one-pass integrator based on Gauss rule diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt index 7eca90f88..56647bace 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt @@ -6,36 +6,53 @@ package space.kscience.kmath.integration import space.kscience.kmath.operations.Field -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.operations.sum /** + * Use double pass Simpson rule integration with a fixed number of points. + * Requires [UnivariateIntegrandRanges] or [IntegrationRange] and [IntegrandMaxCalls] * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 10 points. */ public class SimpsonIntegrator( public val algebra: Field, - public val bufferFactory: BufferFactory, ) : UnivariateIntegrator { - override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand = with(algebra) { - val numPoints = integrand.getFeature()?.maxCalls ?: 100 - require(numPoints >= 4) - val range = integrand.getFeature()?.range ?: 0.0..1.0 + + private fun integrateRange( + integrand: UnivariateIntegrand, range: ClosedRange, numPoints: Int, + ): T = algebra { val h: Double = (range.endInclusive - range.start) / (numPoints - 1) - val points: Buffer = bufferFactory(numPoints) { i -> + val values: List = List(numPoints) { i -> integrand.function(range.start + i * h) }// equally distributed point - fun simpson(index: Int) = h / 3 * (points[index - 1] + 4 * points[index] + points[index + 1]) + //TODO don't use list, reassign values instead + fun simpson(index: Int) = h / 3 * (values[index - 1] + 4 * values[index] + values[index + 1]) + var res = zero res += simpson(1) / 1.5 //border points with 1.5 factor - for (i in 2 until (points.size - 2)) { + for (i in 2 until (values.size - 2)) { + //each half-interval is computed twice, therefore /2 res += simpson(i) / 2 } - res += simpson(points.size - 2) / 1.5 //border points with 1.5 factor - return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + points.size) + res += simpson(values.size - 2) / 1.5 //border points with 1.5 factor + return res + } + + override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand { + val ranges = integrand.getFeature() + return if (ranges != null) { + val res = algebra.sum(ranges.ranges.map { integrateRange(integrand, it.first, it.second) }) + integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + ranges.ranges.sumOf { it.second }) + } else { + val numPoints = integrand.getFeature()?.maxCalls ?: 100 + require(numPoints >= 4) { "Simpson integrator requires at least 4 nodes" } + val range = integrand.getFeature()?.range ?: 0.0..1.0 + val res = integrateRange(integrand, range, numPoints) + integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + numPoints) + } } } -public inline val Field.simpsonIntegrator: SimpsonIntegrator - get() = SimpsonIntegrator(this, Buffer.Companion::auto) \ No newline at end of file +public val Field.simpsonIntegrator: SimpsonIntegrator get() = SimpsonIntegrator(this) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt index da5730497..23d7bdd8d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt @@ -5,8 +5,98 @@ package space.kscience.kmath.integration -public class SplineIntegrator: UnivariateIntegrator { - override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand { - TODO("Not yet implemented") +import space.kscience.kmath.functions.PiecewisePolynomial +import space.kscience.kmath.functions.integrate +import space.kscience.kmath.interpolation.PolynomialInterpolator +import space.kscience.kmath.interpolation.SplineInterpolator +import space.kscience.kmath.interpolation.interpolatePolynomials +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.operations.sum +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.MutableBufferFactory +import space.kscience.kmath.structures.map + +/** + * Compute analytical indefinite integral of this [PiecewisePolynomial], keeping all intervals intact + */ +@UnstableKMathAPI +public fun > PiecewisePolynomial.integrate(algebra: Field): PiecewisePolynomial = + PiecewisePolynomial(pieces.map { it.first to it.second.integrate(algebra) }) + +/** + * Compute definite integral of given [PiecewisePolynomial] piece by piece in a given [range] + * Requires [UnivariateIntegrationNodes] or [IntegrationRange] and [IntegrandMaxCalls] + */ +@UnstableKMathAPI +public fun > PiecewisePolynomial.integrate( + algebra: Field, range: ClosedRange, +): T = algebra.sum( + pieces.map { (region, poly) -> + val intersectedRange = maxOf(range.start, region.start)..minOf(range.endInclusive, region.endInclusive) + //Check if polynomial range is not used + if (intersectedRange.start == intersectedRange.endInclusive) algebra.zero + else poly.integrate(algebra, intersectedRange) } -} \ No newline at end of file +) + +/** + * A generic spline-interpolation-based analytic integration + * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. + * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 10 points. + */ +@UnstableKMathAPI +public class SplineIntegrator>( + public val algebra: Field, + public val bufferFactory: MutableBufferFactory, +) : UnivariateIntegrator { + override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand = algebra { + val range = integrand.getFeature()?.range ?: 0.0..1.0 + + val interpolator: PolynomialInterpolator = SplineInterpolator(algebra, bufferFactory) + val nodes: Buffer = integrand.getFeature()?.nodes ?: run { + val numPoints = integrand.getFeature()?.maxCalls ?: 100 + val step = (range.endInclusive - range.start) / (numPoints - 1) + DoubleBuffer(numPoints) { i -> range.start + i * step } + } + + val values = nodes.map(bufferFactory) { integrand.function(it) } + val polynomials = interpolator.interpolatePolynomials( + nodes.map(bufferFactory) { number(it) }, + values + ) + val res = polynomials.integrate(algebra, number(range.start)..number(range.endInclusive)) + integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + nodes.size) + } +} + +/** + * A simplified double-based spline-interpolation-based analytic integration + * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. + * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 10 points. + */ +@UnstableKMathAPI +public object DoubleSplineIntegrator : UnivariateIntegrator { + override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand { + val range = integrand.getFeature()?.range ?: 0.0..1.0 + + val interpolator: PolynomialInterpolator = SplineInterpolator(DoubleField, ::DoubleBuffer) + val nodes: Buffer = integrand.getFeature()?.nodes ?: run { + val numPoints = integrand.getFeature()?.maxCalls ?: 100 + val step = (range.endInclusive - range.start) / (numPoints - 1) + DoubleBuffer(numPoints) { i -> range.start + i * step } + } + + val values = nodes.map { integrand.function(it) } + val polynomials = interpolator.interpolatePolynomials(nodes, values) + val res = polynomials.integrate(DoubleField, range) + return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + nodes.size) + } +} + +@UnstableKMathAPI +public inline val DoubleField.splineIntegrator: UnivariateIntegrator + get() = DoubleSplineIntegrator \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index d3d0220f6..8c515065f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -6,6 +6,8 @@ package space.kscience.kmath.integration import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.DoubleBuffer import kotlin.jvm.JvmInline import kotlin.reflect.KClass @@ -35,6 +37,19 @@ public typealias UnivariateIntegrator = Integrator> @JvmInline public value class IntegrationRange(public val range: ClosedRange) : IntegrandFeature +/** + * Set of univariate integration ranges. First components correspond to ranges themselves, second components to number of + * integration nodes per range + */ +public class UnivariateIntegrandRanges(public val ranges: List, Int>>) : IntegrandFeature { + public constructor(vararg pairs: Pair, Int>) : this(pairs.toList()) +} + +public class UnivariateIntegrationNodes(public val nodes: Buffer) : IntegrandFeature { + public constructor(vararg nodes: Double) : this(DoubleBuffer(nodes)) +} + + /** * Value of the integrand if it is present or null */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt index 08090a522..c9ec0d527 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -15,10 +15,16 @@ import space.kscience.kmath.operations.Ring import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer +/** + * And interpolator for data with x column type [X], y column type [Y]. + */ public fun interface Interpolator { public fun interpolate(points: XYColumnarData): (X) -> Y } +/** + * And interpolator returning [PiecewisePolynomial] function + */ public interface PolynomialInterpolator> : Interpolator { public val algebra: Ring diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt index b0c0cd098..9f2d71554 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt @@ -24,8 +24,8 @@ class SimpsonIntegralTest { @Test fun gaussUniform() { - val res = DoubleField.simpsonIntegrator.integrate(35.0..100.0) { x -> - if(x in 30.0..50.0){ + val res = DoubleField.simpsonIntegrator.integrate(35.0..100.0, IntegrandMaxCalls(20)) { x -> + if (x in 30.0..50.0) { 1.0 } else { 0.0 @@ -33,6 +33,4 @@ class SimpsonIntegralTest { } assertEquals(15.0, res.value, 0.5) } - - } \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt new file mode 100644 index 000000000..afeba0be4 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt @@ -0,0 +1,48 @@ +/* + * 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.integration + +import space.kscience.kmath.functions.Polynomial +import space.kscience.kmath.functions.integrate +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.DoubleField +import kotlin.math.PI +import kotlin.math.sin +import kotlin.test.Test +import kotlin.test.assertEquals + +@OptIn(UnstableKMathAPI::class) +class SplineIntegralTest { + + @Test + fun integratePolynomial(){ + val polynomial = Polynomial(1.0, 2.0, 3.0) + val integral = polynomial.integrate(DoubleField,1.0..2.0) + assertEquals(11.0, integral, 0.001) + } + + @Test + fun gaussSin() { + val res = DoubleField.splineIntegrator.integrate(0.0..2 * PI, IntegrandMaxCalls(5)) { x -> + sin(x) + } + assertEquals(0.0, res.value, 1e-2) + } + + @Test + fun gaussUniform() { + val res = DoubleField.splineIntegrator.integrate(35.0..100.0, IntegrandMaxCalls(20)) { x -> + if(x in 30.0..50.0){ + 1.0 + } else { + 0.0 + } + } + assertEquals(15.0, res.value, 0.5) + } + + +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index cc9eb4860..065dd3ac4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,11 +1,11 @@ pluginManagement { repositories { + maven("https://repo.kotlin.link") mavenCentral() gradlePluginPortal() - maven("https://repo.kotlin.link") } - val toolsVersion = "0.9.8" + val toolsVersion = "0.9.9" val kotlinVersion = "1.5.0" plugins { @@ -15,8 +15,8 @@ pluginManagement { kotlin("multiplatform") version kotlinVersion kotlin("jvm") version kotlinVersion kotlin("plugin.allopen") version kotlinVersion - id("org.jetbrains.kotlinx.benchmark") version "0.3.0" - kotlin("jupyter.api") version "0.9.1-61" + id("org.jetbrains.kotlinx.benchmark") version "0.3.1" + kotlin("jupyter.api") version "0.10.0-25" } } From ec7a971df71e4371c2720ffb77d2c3dafbd0c0bf Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 22 May 2021 20:17:52 +0300 Subject: [PATCH 371/393] Separate double-based integrator for a Simpson rule --- build.gradle.kts | 3 +- .../kmath/integration/SimpsonIntegrator.kt | 51 ++++++++++++++++++- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index d44833445..ef9c60c55 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,13 +10,12 @@ allprojects { maven("http://logicrunch.research.it.uu.se/maven") { isAllowInsecureProtocol = true } - maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven") maven("https://oss.sonatype.org/content/repositories/snapshots") mavenCentral() } group = "space.kscience" - version = "0.3.0-dev-11" + version = "0.3.0-dev-12" } subprojects { diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt index 56647bace..baa9d4af8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt @@ -5,6 +5,8 @@ package space.kscience.kmath.integration +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.sum @@ -15,6 +17,7 @@ import space.kscience.kmath.operations.sum * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 10 points. */ +@UnstableKMathAPI public class SimpsonIntegrator( public val algebra: Field, ) : UnivariateIntegrator { @@ -55,4 +58,50 @@ public class SimpsonIntegrator( } } -public val Field.simpsonIntegrator: SimpsonIntegrator get() = SimpsonIntegrator(this) \ No newline at end of file +@UnstableKMathAPI +public val Field.simpsonIntegrator: SimpsonIntegrator get() = SimpsonIntegrator(this) + +/** + * Use double pass Simpson rule integration with a fixed number of points. + * Requires [UnivariateIntegrandRanges] or [IntegrationRange] and [IntegrandMaxCalls] + * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval. + * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 10 points. + */ +public object DoubleSimpsonIntegrator : UnivariateIntegrator { + + private fun integrateRange( + integrand: UnivariateIntegrand, range: ClosedRange, numPoints: Int, + ): Double { + val h: Double = (range.endInclusive - range.start) / (numPoints - 1) + val values = DoubleArray(numPoints) { i -> + integrand.function(range.start + i * h) + }// equally distributed point + + fun simpson(index: Int) = h / 3 * (values[index - 1] + 4 * values[index] + values[index + 1]) + + var res = 0.0 + res += simpson(1) / 1.5 //border points with 1.5 factor + for (i in 2 until (values.size - 2)) { + //each half-interval is computed twice, therefore /2 + res += simpson(i) / 2 + } + res += simpson(values.size - 2) / 1.5 //border points with 1.5 factor + return res + } + + override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand { + val ranges = integrand.getFeature() + return if (ranges != null) { + val res = ranges.ranges.sumOf { integrateRange(integrand, it.first, it.second) } + integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + ranges.ranges.sumOf { it.second }) + } else { + val numPoints = integrand.getFeature()?.maxCalls ?: 100 + require(numPoints >= 4) { "Simpson integrator requires at least 4 nodes" } + val range = integrand.getFeature()?.range ?: 0.0..1.0 + val res = integrateRange(integrand, range, numPoints) + integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + numPoints) + } + } +} + +public val DoubleField.simpsonIntegrator: DoubleSimpsonIntegrator get() = DoubleSimpsonIntegrator \ No newline at end of file From 380c76fe40d2cdaeca9731aeb0d5b54b225ea37a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 23 May 2021 20:01:07 +0300 Subject: [PATCH 372/393] Piecewise optimization --- build.gradle.kts | 2 +- .../space/kscience/kmath/misc/annotations.kt | 4 +- .../kscience/kmath/functions/Piecewise.kt | 49 ++++++++++++++----- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ef9c60c55..4de6d8bad 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.0-dev-12" + version = "0.3.0-dev-13" } subprojects { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt index 18718de97..e521e6237 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt @@ -26,4 +26,6 @@ public annotation class UnstableKMathAPI "Refer to the documentation to use this API in performance-critical code", RequiresOptIn.Level.WARNING ) -public annotation class PerformancePitfall +public annotation class PerformancePitfall( + val message: String = "Potential performance problem" +) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index dd9c571b0..73fa57c7b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.functions +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.operations.Ring /** @@ -24,17 +25,43 @@ public fun interface Piecewise { * Represents piecewise-defined function where all the sub-functions are polynomials. * @param pieces An ordered list of range-polynomial pairs. The list does not in general guarantee that there are no "holes" in it. */ -public class PiecewisePolynomial>( - public val pieces: List, Polynomial>>, -) : Piecewise> { +public interface PiecewisePolynomial> : Piecewise> { + public val pieces: Collection, Polynomial>> - public override fun findPiece(arg: T): Polynomial? { - return if (arg < pieces.first().first.start || arg >= pieces.last().first.endInclusive) - null - else { - pieces.firstOrNull { arg in it.first }?.second + public override fun findPiece(arg: T): Polynomial? +} + +/** + * A generic piecewise without constraints on how pieces are placed + */ +@PerformancePitfall("findPiece method of resulting piecewise is slow") +public fun > PiecewisePolynomial( + pieces: Collection, Polynomial>>, +): PiecewisePolynomial = object : PiecewisePolynomial { + override val pieces: Collection, Polynomial>> = pieces + + override fun findPiece(arg: T): Polynomial? = pieces.firstOrNull { arg in it.first }?.second +} + +/** + * An optimized piecewise which uses not separate pieces, but a range separated by delimiters. + * The pices search is logarithmic + */ +private class OrderedPiecewisePolynomial>( + override val pieces: List, Polynomial>>, +) : PiecewisePolynomial { + + override fun findPiece(arg: T): Polynomial? { + val index = pieces.binarySearch { (range, _) -> + when { + arg >= range.endInclusive -> -1 + arg < range.start -> +1 + else -> 0 + } } + return if (index < 0) null else pieces[index].second } + } /** @@ -71,9 +98,9 @@ public class PiecewiseBuilder>(delimiter: T) { pieces.add(0, piece) } - public fun build(): PiecewisePolynomial { - return PiecewisePolynomial(delimiters.zipWithNext { l, r -> l..r }.zip(pieces)) - } + public fun build(): PiecewisePolynomial = OrderedPiecewisePolynomial(delimiters.zipWithNext { l, r -> + l..r + }.zip(pieces)) } /** From 12805712d3a42092c7b4ca65c1fd2507acf2c0f3 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 24 May 2021 14:30:51 +0300 Subject: [PATCH 373/393] Integrand toString --- .../kmath/commons/integration/CMIntegrator.kt | 41 ++++++++----------- .../integration/GaussIntegratorRuleFactory.kt | 2 + .../kscience/kmath/integration/Integrand.kt | 29 ++++++++++--- .../integration/MultivariateIntegrand.kt | 8 ++-- .../kmath/integration/UnivariateIntegrand.kt | 29 +++++++++---- 5 files changed, 66 insertions(+), 43 deletions(-) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt index 92bf86128..bcddccdc4 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt @@ -18,12 +18,6 @@ public class CMIntegrator( public val integratorBuilder: (Integrand) -> org.apache.commons.math3.analysis.integration.UnivariateIntegrator, ) : UnivariateIntegrator { - public class TargetRelativeAccuracy(public val value: Double) : IntegrandFeature - public class TargetAbsoluteAccuracy(public val value: Double) : IntegrandFeature - - public class MinIterations(public val value: Int) : IntegrandFeature - public class MaxIterations(public val value: Int) : IntegrandFeature - override fun integrate(integrand: UnivariateIntegrand): UnivariateIntegrand { val integrator = integratorBuilder(integrand) val maxCalls = integrand.getFeature()?.maxCalls ?: defaultMaxCalls @@ -45,16 +39,15 @@ public class CMIntegrator( * Create a Simpson integrator based on [SimpsonIntegrator] */ public fun simpson(defaultMaxCalls: Int = 200): CMIntegrator = CMIntegrator(defaultMaxCalls) { integrand -> - val absoluteAccuracy = integrand.getFeature()?.value + val absoluteAccuracy = integrand.getFeature()?.accuracy ?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY - val relativeAccuracy = integrand.getFeature()?.value + val relativeAccuracy = integrand.getFeature()?.accuracy ?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY - val minIterations = integrand.getFeature()?.value - ?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT - val maxIterations = integrand.getFeature()?.value - ?: SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT + val iterations = integrand.getFeature()?.range + ?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT..SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT - SimpsonIntegrator(relativeAccuracy, absoluteAccuracy, minIterations, maxIterations) + + SimpsonIntegrator(relativeAccuracy, absoluteAccuracy, iterations.first, iterations.last) } /** @@ -62,21 +55,19 @@ public class CMIntegrator( */ public fun legandre(numPoints: Int, defaultMaxCalls: Int = numPoints * 5): CMIntegrator = CMIntegrator(defaultMaxCalls) { integrand -> - val absoluteAccuracy = integrand.getFeature()?.value + val absoluteAccuracy = integrand.getFeature()?.accuracy ?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY - val relativeAccuracy = integrand.getFeature()?.value + val relativeAccuracy = integrand.getFeature()?.accuracy ?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY - val minIterations = integrand.getFeature()?.value - ?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT - val maxIterations = integrand.getFeature()?.value - ?: IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT + val iterations = integrand.getFeature()?.range + ?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT..IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT IterativeLegendreGaussIntegrator( numPoints, relativeAccuracy, absoluteAccuracy, - minIterations, - maxIterations + iterations.first, + iterations.last ) } } @@ -84,14 +75,14 @@ public class CMIntegrator( @UnstableKMathAPI public var MutableList.targetAbsoluteAccuracy: Double? - get() = filterIsInstance().lastOrNull()?.value + get() = filterIsInstance().lastOrNull()?.accuracy set(value) { - value?.let { add(CMIntegrator.TargetAbsoluteAccuracy(value)) } + value?.let { add(IntegrandAbsoluteAccuracy(value)) } } @UnstableKMathAPI public var MutableList.targetRelativeAccuracy: Double? - get() = filterIsInstance().lastOrNull()?.value + get() = filterIsInstance().lastOrNull()?.accuracy set(value) { - value?.let { add(CMIntegrator.TargetRelativeAccuracy(value)) } + value?.let { add(IntegrandRelativeAccuracy(value)) } } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt index 133f829e3..594ca9940 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt @@ -164,4 +164,6 @@ public object GaussLegendreRuleFactory : GaussIntegratorRuleFactory { } override fun build(numPoints: Int): Pair, Buffer> = getOrBuildRule(numPoints) + + override fun toString(): String = "GaussLegendreRule" } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt index 1ff8e422e..f9c26e88b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt @@ -7,22 +7,39 @@ package space.kscience.kmath.integration import kotlin.reflect.KClass -public interface IntegrandFeature +public interface IntegrandFeature { + override fun toString(): String +} public interface Integrand { + public val features: Set public fun getFeature(type: KClass): T? } public inline fun Integrand.getFeature(): T? = getFeature(T::class) -public class IntegrandValue(public val value: T) : IntegrandFeature +public class IntegrandValue(public val value: T) : IntegrandFeature { + override fun toString(): String = "Value($value)" +} -public class IntegrandRelativeAccuracy(public val accuracy: Double) : IntegrandFeature +public class IntegrandRelativeAccuracy(public val accuracy: Double) : IntegrandFeature { + override fun toString(): String = "TargetRelativeAccuracy($accuracy)" +} -public class IntegrandAbsoluteAccuracy(public val accuracy: Double) : IntegrandFeature +public class IntegrandAbsoluteAccuracy(public val accuracy: Double) : IntegrandFeature { + override fun toString(): String = "TargetAbsoluteAccuracy($accuracy)" +} -public class IntegrandCallsPerformed(public val calls: Int) : IntegrandFeature +public class IntegrandCallsPerformed(public val calls: Int) : IntegrandFeature { + override fun toString(): String = "Calls($calls)" +} public val Integrand.calls: Int get() = getFeature()?.calls ?: 0 -public class IntegrandMaxCalls(public val maxCalls: Int) : IntegrandFeature +public class IntegrandMaxCalls(public val maxCalls: Int) : IntegrandFeature { + override fun toString(): String = "MaxCalls($maxCalls)" +} + +public class IntegrandIterationsRange(public val range: IntRange) : IntegrandFeature { + override fun toString(): String = "Iterations(${range.first}..${range.last})" +} diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt index 12d0ef0a6..5ba411bf9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt @@ -9,15 +9,17 @@ import space.kscience.kmath.linear.Point import kotlin.reflect.KClass public class MultivariateIntegrand internal constructor( - private val features: Map, IntegrandFeature>, + private val featureMap: Map, IntegrandFeature>, public val function: (Point) -> T, ) : Integrand { + override val features: Set get() = featureMap.values.toSet() + @Suppress("UNCHECKED_CAST") - override fun getFeature(type: KClass): T? = features[type] as? T + override fun getFeature(type: KClass): T? = featureMap[type] as? T public operator fun plus(pair: Pair, F>): MultivariateIntegrand = - MultivariateIntegrand(features + pair, function) + MultivariateIntegrand(featureMap + pair, function) public operator fun plus(feature: F): MultivariateIntegrand = plus(feature::class to feature) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index 8c515065f..e265f54e8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -8,19 +8,20 @@ package space.kscience.kmath.integration import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer -import kotlin.jvm.JvmInline import kotlin.reflect.KClass public class UnivariateIntegrand internal constructor( - private val features: Map, IntegrandFeature>, + private val featureMap: Map, IntegrandFeature>, public val function: (Double) -> T, ) : Integrand { + override val features: Set get() = featureMap.values.toSet() + @Suppress("UNCHECKED_CAST") - override fun getFeature(type: KClass): T? = features[type] as? T + override fun getFeature(type: KClass): T? = featureMap[type] as? T public operator fun plus(pair: Pair, F>): UnivariateIntegrand = - UnivariateIntegrand(features + pair, function) + UnivariateIntegrand(featureMap + pair, function) public operator fun plus(feature: F): UnivariateIntegrand = plus(feature::class to feature) @@ -34,8 +35,9 @@ public fun UnivariateIntegrand( public typealias UnivariateIntegrator = Integrator> -@JvmInline -public value class IntegrationRange(public val range: ClosedRange) : IntegrandFeature +public class IntegrationRange(public val range: ClosedRange) : IntegrandFeature { + override fun toString(): String = "Range(${range.start}..${range.endInclusive})" +} /** * Set of univariate integration ranges. First components correspond to ranges themselves, second components to number of @@ -43,10 +45,19 @@ public value class IntegrationRange(public val range: ClosedRange) : Int */ public class UnivariateIntegrandRanges(public val ranges: List, Int>>) : IntegrandFeature { public constructor(vararg pairs: Pair, Int>) : this(pairs.toList()) + + override fun toString(): String { + val rangesString = ranges.joinToString(separator = ",") { (range, points) -> + "${range.start}..${range.endInclusive} : $points" + } + return "UnivariateRanges($rangesString)" + } } public class UnivariateIntegrationNodes(public val nodes: Buffer) : IntegrandFeature { public constructor(vararg nodes: Double) : this(DoubleBuffer(nodes)) + + override fun toString(): String = "UnivariateNodes($nodes)" } @@ -65,7 +76,7 @@ public val UnivariateIntegrand.value: T get() = valueOrNull ?: erro * The [function] is placed in the end position to allow passing a lambda. */ @UnstableKMathAPI -public fun UnivariateIntegrator.integrate( +public fun UnivariateIntegrator.integrate( vararg features: IntegrandFeature, function: (Double) -> T, ): UnivariateIntegrand = integrate(UnivariateIntegrand(function, *features)) @@ -75,7 +86,7 @@ public fun UnivariateIntegrator.integrate( * The [function] is placed in the end position to allow passing a lambda. */ @UnstableKMathAPI -public fun UnivariateIntegrator.integrate( +public fun UnivariateIntegrator.integrate( range: ClosedRange, vararg features: IntegrandFeature, function: (Double) -> T, @@ -86,7 +97,7 @@ public fun UnivariateIntegrator.integrate( * The [function] is placed in the end position to allow passing a lambda. */ @UnstableKMathAPI -public fun UnivariateIntegrator.integrate( +public fun UnivariateIntegrator.integrate( range: ClosedRange, featureBuilder: MutableList.() -> Unit = {}, function: (Double) -> T, From f2b7a08ad8018d508a1edc3c5af9894fb89bafd5 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 25 May 2021 16:53:53 +0300 Subject: [PATCH 374/393] Remove second generic from DifferentiableExpression --- CHANGELOG.md | 1 + .../DerivativeStructureExpression.kt | 4 +-- .../commons/optimization/CMOptimization.kt | 9 +---- .../kmath/commons/optimization/cmFit.kt | 8 ++--- .../expressions/DifferentiableExpression.kt | 34 ++++++++++++++----- .../kmath/expressions/SimpleAutoDiff.kt | 2 +- .../kmath/kotlingrad/KotlingradExpression.kt | 2 +- .../optimization/FunctionOptimization.kt | 6 ++-- .../kscience/kmath/optimization/XYFit.kt | 2 +- 9 files changed, 39 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c6b14b95..524d2a1de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ - MSTExpression - Expression algebra builders - Complex and Quaternion no longer are elements. +- Second generic from DifferentiableExpression ### Fixed - Ring inherits RingOperations, not GroupOperations diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 89e216601..361027968 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -106,7 +106,7 @@ public class DerivativeStructureField( public companion object : AutoDiffProcessor> { - public override fun process(function: DerivativeStructureField.() -> DerivativeStructure): DifferentiableExpression> = + public override fun process(function: DerivativeStructureField.() -> DerivativeStructure): DifferentiableExpression = DerivativeStructureExpression(function) } } @@ -116,7 +116,7 @@ public class DerivativeStructureField( */ public class DerivativeStructureExpression( public val function: DerivativeStructureField.() -> DerivativeStructure, -) : DifferentiableExpression> { +) : DifferentiableExpression { public override operator fun invoke(arguments: Map): Double = DerivativeStructureField(0, arguments).function().value diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt index bca00de46..400ee0310 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimization.kt @@ -17,14 +17,7 @@ import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer import space.kscience.kmath.expressions.* import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.optimization.* -import kotlin.collections.HashMap -import kotlin.collections.List -import kotlin.collections.Map import kotlin.collections.set -import kotlin.collections.setOf -import kotlin.collections.toList -import kotlin.collections.toMap -import kotlin.collections.toTypedArray import kotlin.reflect.KClass public operator fun PointValuePair.component1(): DoubleArray = point @@ -71,7 +64,7 @@ public class CMOptimization( addOptimizationData(objectiveFunction) } - public override fun diffFunction(expression: DifferentiableExpression>) { + public override fun diffFunction(expression: DifferentiableExpression) { function(expression) val gradientFunction = ObjectiveFunctionGradient { val args = it.toMap() diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt index a5a913623..645c41291 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/cmFit.kt @@ -25,7 +25,7 @@ public fun FunctionOptimization.Companion.chiSquared( y: Buffer, yErr: Buffer, model: DerivativeStructureField.(x: DerivativeStructure) -> DerivativeStructure, -): DifferentiableExpression> = chiSquared(DerivativeStructureField, x, y, yErr, model) +): DifferentiableExpression = chiSquared(DerivativeStructureField, x, y, yErr, model) /** * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation @@ -35,7 +35,7 @@ public fun FunctionOptimization.Companion.chiSquared( y: Iterable, yErr: Iterable, model: DerivativeStructureField.(x: DerivativeStructure) -> DerivativeStructure, -): DifferentiableExpression> = chiSquared( +): DifferentiableExpression = chiSquared( DerivativeStructureField, x.toList().asBuffer(), y.toList().asBuffer(), @@ -54,12 +54,12 @@ public fun Expression.optimize( /** * Optimize differentiable expression */ -public fun DifferentiableExpression>.optimize( +public fun DifferentiableExpression.optimize( vararg symbols: Symbol, configuration: CMOptimization.() -> Unit, ): OptimizationResult = optimizeWith(CMOptimization, symbols = symbols, configuration) -public fun DifferentiableExpression>.minimize( +public fun DifferentiableExpression.minimize( vararg startPoint: Pair, configuration: CMOptimization.() -> Unit = {}, ): OptimizationResult { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt index 33d72afad..1dcada6d3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt @@ -11,35 +11,51 @@ package space.kscience.kmath.expressions * @param T the type this expression takes as argument and returns. * @param R the type of expression this expression can be differentiated to. */ -public interface DifferentiableExpression> : Expression { +public interface DifferentiableExpression : Expression { /** * Differentiates this expression by ordered collection of [symbols]. * * @param symbols the symbols. * @return the derivative or `null`. */ - public fun derivativeOrNull(symbols: List): R? + public fun derivativeOrNull(symbols: List): Expression? } -public fun > DifferentiableExpression.derivative(symbols: List): R = +public fun DifferentiableExpression.derivative(symbols: List): Expression = derivativeOrNull(symbols) ?: error("Derivative by symbols $symbols not provided") -public fun > DifferentiableExpression.derivative(vararg symbols: Symbol): R = +public fun DifferentiableExpression.derivative(vararg symbols: Symbol): Expression = derivative(symbols.toList()) -public fun > DifferentiableExpression.derivative(name: String): R = +public fun DifferentiableExpression.derivative(name: String): Expression = + derivative(StringSymbol(name)) + +/** + * A special type of [DifferentiableExpression] which returns typed expressions as derivatives + */ +public interface SpecialDifferentiableExpression>: DifferentiableExpression { + override fun derivativeOrNull(symbols: List): R? +} + +public fun > SpecialDifferentiableExpression.derivative(symbols: List): R = + derivativeOrNull(symbols) ?: error("Derivative by symbols $symbols not provided") + +public fun > SpecialDifferentiableExpression.derivative(vararg symbols: Symbol): R = + derivative(symbols.toList()) + +public fun > SpecialDifferentiableExpression.derivative(name: String): R = derivative(StringSymbol(name)) /** * A [DifferentiableExpression] that defines only first derivatives */ -public abstract class FirstDerivativeExpression> : DifferentiableExpression { +public abstract class FirstDerivativeExpression : DifferentiableExpression { /** * Returns first derivative of this expression by given [symbol]. */ - public abstract fun derivativeOrNull(symbol: Symbol): R? + public abstract fun derivativeOrNull(symbol: Symbol): Expression? - public final override fun derivativeOrNull(symbols: List): R? { + public final override fun derivativeOrNull(symbols: List): Expression? { val dSymbol = symbols.firstOrNull() ?: return null return derivativeOrNull(dSymbol) } @@ -49,5 +65,5 @@ public abstract class FirstDerivativeExpression> : Differen * A factory that converts an expression in autodiff variables to a [DifferentiableExpression] */ public fun interface AutoDiffProcessor, out R : Expression> { - public fun process(function: A.() -> I): DifferentiableExpression + public fun process(function: A.() -> I): DifferentiableExpression } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt index 254d60b3d..478b85620 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -232,7 +232,7 @@ public fun > F.simpleAutoDiff( public class SimpleAutoDiffExpression>( public val field: F, public val function: SimpleAutoDiffField.() -> AutoDiffValue, -) : FirstDerivativeExpression>() { +) : FirstDerivativeExpression() { public override operator fun invoke(arguments: Map): T { //val bindings = arguments.entries.map { it.key.bind(it.value) } return SimpleAutoDiffField(field, arguments).function().value diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt index 72ecee4f1..4294462c0 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt @@ -24,7 +24,7 @@ import space.kscience.kmath.operations.NumericAlgebra public class KotlingradExpression>( public val algebra: A, public val mst: MST, -) : DifferentiableExpression> { +) : SpecialDifferentiableExpression> { public override fun invoke(arguments: Map): T = mst.interpret(algebra, arguments) public override fun derivativeOrNull(symbols: List): KotlingradExpression = diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt index 4cf5aea84..f54ba5723 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt @@ -27,7 +27,7 @@ public interface FunctionOptimization : Optimization { /** * Set a differentiable expression as objective function as function and gradient provider */ - public fun diffFunction(expression: DifferentiableExpression>) + public fun diffFunction(expression: DifferentiableExpression) public companion object { /** @@ -39,7 +39,7 @@ public interface FunctionOptimization : Optimization { y: Buffer, yErr: Buffer, model: A.(I) -> I, - ): DifferentiableExpression> where A : ExtendedField, A : ExpressionAlgebra { + ): DifferentiableExpression where A : ExtendedField, A : ExpressionAlgebra { require(x.size == y.size) { "X and y buffers should be of the same size" } require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } @@ -78,7 +78,7 @@ public fun FunctionOptimization.chiSquared( /** * Optimize differentiable expression using specific [OptimizationProblemFactory] */ -public fun > DifferentiableExpression>.optimizeWith( +public fun > DifferentiableExpression.optimizeWith( factory: OptimizationProblemFactory, vararg symbols: Symbol, configuration: F.() -> Unit, diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt index 633e9ae0e..70d7fdf79 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt @@ -27,7 +27,7 @@ public interface XYFit : Optimization { yErrSymbol: Symbol? = null, ) - public fun model(model: (T) -> DifferentiableExpression) + public fun model(model: (T) -> DifferentiableExpression) /** * Set the differentiable model for this fit From 65e05605533a033fff621b83a447c7a78a07cd58 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 29 May 2021 15:50:16 +0700 Subject: [PATCH 375/393] Fix Symja build issues --- build.gradle.kts | 5 ++++- kmath-symja/build.gradle.kts | 9 ++++++++- .../space/kscience/kmath/symja/SymjaExpression.kt | 15 +++++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4de6d8bad..1826a2e7e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,9 @@ allprojects { maven("http://logicrunch.research.it.uu.se/maven") { isAllowInsecureProtocol = true } - maven("https://oss.sonatype.org/content/repositories/snapshots") + maven("https://oss.sonatype.org/content/repositories/snapshots") { + + } mavenCentral() } @@ -31,6 +33,7 @@ subprojects { externalDocumentationLink("http://ejml.org/javadoc/") externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/") externalDocumentationLink("https://deeplearning4j.org/api/latest/") + externalDocumentationLink("https://axelclk.bitbucket.io/symja/javadoc/") externalDocumentationLink("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/") } } diff --git a/kmath-symja/build.gradle.kts b/kmath-symja/build.gradle.kts index c06020bb6..c67b42e3f 100644 --- a/kmath-symja/build.gradle.kts +++ b/kmath-symja/build.gradle.kts @@ -11,7 +11,14 @@ plugins { description = "Symja integration module" dependencies { - api("org.matheclipse:matheclipse-core:2.0.0-SNAPSHOT") + api("org.matheclipse:matheclipse-core:2.0.0-SNAPSHOT") { + // Incorrect transitive dependency org.apfloat:apfloat:1.10.0-SNAPSHOT + exclude("org.apfloat", "apfloat") + } + + // Replace for org.apfloat:apfloat:1.10.0-SNAPSHOT + api("org.apfloat:apfloat:1.10.0") + api(project(":kmath-core")) testImplementation("org.slf4j:slf4j-simple:1.7.30") } diff --git a/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt index 301678916..a6773c709 100644 --- a/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt +++ b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt @@ -7,17 +7,28 @@ package space.kscience.kmath.symja import org.matheclipse.core.eval.ExprEvaluator import org.matheclipse.core.expression.F -import space.kscience.kmath.expressions.DifferentiableExpression +import space.kscience.kmath.expressions.SpecialDifferentiableExpression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.interpret import space.kscience.kmath.operations.NumericAlgebra +/** + * Represents [MST] based [DifferentiableExpression] relying on [Symja](https://github.com/axkr/symja_android_library). + * + * The principle of this API is converting the [mst] to an [org.matheclipse.core.interfaces.IExpr], differentiating it + * with Symja's [F.D], then converting [org.matheclipse.core.interfaces.IExpr] back to [MST]. + * + * @param T The type of number. + * @param A The [NumericAlgebra] of [T]. + * @property algebra The [A] instance. + * @property mst The [MST] node. + */ public class SymjaExpression>( public val algebra: A, public val mst: MST, public val evaluator: ExprEvaluator = DEFAULT_EVALUATOR, -) : DifferentiableExpression> { +) : SpecialDifferentiableExpression> { public override fun invoke(arguments: Map): T = mst.interpret(algebra, arguments) public override fun derivativeOrNull(symbols: List): SymjaExpression = SymjaExpression( From 7d0eff74f6b48f26d16343f5a0c4e9d38fe73e68 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 8 Jun 2021 20:39:47 +0700 Subject: [PATCH 376/393] Fix shield README.md, fix build --- README.md | 2 +- docs/templates/README-TEMPLATE.md | 2 +- kmath-symja/build.gradle.kts | 18 ++++++++++++++++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9117582ac..dfb9cba9c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) [![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22) -[![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fkscience%2Fkmath%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) +[![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) # KMath diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index 6bb1e9085..c981cb0bd 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -2,7 +2,7 @@ [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) [![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22) -[![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fkscience%2Fkmath%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) +[![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) # KMath diff --git a/kmath-symja/build.gradle.kts b/kmath-symja/build.gradle.kts index c67b42e3f..f305c03b8 100644 --- a/kmath-symja/build.gradle.kts +++ b/kmath-symja/build.gradle.kts @@ -12,12 +12,26 @@ description = "Symja integration module" dependencies { api("org.matheclipse:matheclipse-core:2.0.0-SNAPSHOT") { - // Incorrect transitive dependency org.apfloat:apfloat:1.10.0-SNAPSHOT + // Incorrect transitive dependencies exclude("org.apfloat", "apfloat") + exclude("org.hipparchus", "hipparchus-clustering") + exclude("org.hipparchus", "hipparchus-core") + exclude("org.hipparchus", "hipparchus-fft") + exclude("org.hipparchus", "hipparchus-fitting") + exclude("org.hipparchus", "hipparchus-ode") + exclude("org.hipparchus", "hipparchus-optim") + exclude("org.hipparchus", "hipparchus-stat") } - // Replace for org.apfloat:apfloat:1.10.0-SNAPSHOT + // Replaces for incorrect transitive dependencies api("org.apfloat:apfloat:1.10.0") + api("org.hipparchus:hipparchus-clustering:1.8") + api("org.hipparchus:hipparchus-core:1.8") + api("org.hipparchus:hipparchus-fft:1.8") + api("org.hipparchus:hipparchus-fitting:1.8") + api("org.hipparchus:hipparchus-ode:1.8") + api("org.hipparchus:hipparchus-optim:1.8") + api("org.hipparchus:hipparchus-stat:1.8") api(project(":kmath-core")) testImplementation("org.slf4j:slf4j-simple:1.7.30") From c0ab082d240d64f3476707912ba4aea31ecae6bc Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 8 Jun 2021 20:53:33 +0700 Subject: [PATCH 377/393] Run build workflow for PRs --- .github/workflows/build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9a9f04621..98f4d2ec2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,9 @@ name: Gradle build -on: [ push ] +on: + push: + pull_request: + types: [opened, edited] jobs: build: From 7b736a7c81391493c48eea54bdb4f263c01b1cb7 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 9 Jun 2021 21:40:47 +0700 Subject: [PATCH 378/393] Fix README.md again --- README.md | 18 ++++++++++++------ docs/templates/README-TEMPLATE.md | 2 +- kmath-ast/README.md | 6 +++--- kmath-complex/README.md | 6 +++--- kmath-core/README.md | 6 +++--- kmath-ejml/README.md | 6 +++--- kmath-for-real/README.md | 6 +++--- kmath-functions/README.md | 6 +++--- kmath-kotlingrad/README.md | 6 +++--- kmath-nd4j/README.md | 6 +++--- kmath-tensors/README.md | 6 +++--- 11 files changed, 40 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index dfb9cba9c..7c6f7ea2b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) [![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22) -[![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) +[![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) # KMath @@ -207,7 +207,7 @@ One can still use generic algebras though.
* ### [kmath-kotlingrad](kmath-kotlingrad) -> Functions, integration and interpolation +> > > **Maturity**: EXPERIMENTAL > @@ -218,13 +218,13 @@ One can still use generic algebras though.
* ### [kmath-memory](kmath-memory) -> An API and basic implementation for arranging objects in a continous memory block. +> An API and basic implementation for arranging objects in a continuous memory block. > > **Maturity**: DEVELOPMENT
* ### [kmath-nd4j](kmath-nd4j) -> ND4J NDStructure implementation and according NDAlgebra classes +> > > **Maturity**: EXPERIMENTAL > @@ -241,6 +241,12 @@ One can still use generic algebras though. > **Maturity**: EXPERIMENTAL
+* ### [kmath-symja](kmath-symja) +> +> +> **Maturity**: PROTOTYPE +
+ * ### [kmath-tensors](kmath-tensors) > > @@ -293,8 +299,8 @@ repositories { } dependencies { - api("space.kscience:kmath-core:0.3.0-dev-11") - // api("space.kscience:kmath-core-jvm:0.3.0-dev-11") for jvm-specific version + api("space.kscience:kmath-core:0.3.0-dev-13") + // api("space.kscience:kmath-core-jvm:0.3.0-dev-13") for jvm-specific version } ``` diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index c981cb0bd..bad11a31a 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -2,7 +2,7 @@ [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) [![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22) -[![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) +[![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) # KMath diff --git a/kmath-ast/README.md b/kmath-ast/README.md index b0f2d59e5..2f6b21094 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -10,7 +10,7 @@ Performance and visualization extensions to MST API. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-11`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-13`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0-dev-11' + implementation 'space.kscience:kmath-ast:0.3.0-dev-13' } ``` **Gradle Kotlin DSL:** @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0-dev-11") + implementation("space.kscience:kmath-ast:0.3.0-dev-13") } ``` diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 04431cf6c..18a83756d 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-11`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-13`. **Gradle:** ```gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0-dev-11' + implementation 'space.kscience:kmath-complex:0.3.0-dev-13' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0-dev-11") + implementation("space.kscience:kmath-complex:0.3.0-dev-13") } ``` diff --git a/kmath-core/README.md b/kmath-core/README.md index 700eaef38..6ca8c8ef8 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-11`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-13`. **Gradle:** ```gradle @@ -25,7 +25,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0-dev-11' + implementation 'space.kscience:kmath-core:0.3.0-dev-13' } ``` **Gradle Kotlin DSL:** @@ -36,6 +36,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0-dev-11") + implementation("space.kscience:kmath-core:0.3.0-dev-13") } ``` diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index 79a28b824..10e7bd606 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-11`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-13`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0-dev-11' + implementation 'space.kscience:kmath-ejml:0.3.0-dev-13' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0-dev-11") + implementation("space.kscience:kmath-ejml:0.3.0-dev-13") } ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 5ca805093..6339782dd 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-11`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-13`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0-dev-11' + implementation 'space.kscience:kmath-for-real:0.3.0-dev-13' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0-dev-11") + implementation("space.kscience:kmath-for-real:0.3.0-dev-13") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 2497f7102..77f55528a 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-11`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-13`. **Gradle:** ```gradle @@ -21,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0-dev-11' + implementation 'space.kscience:kmath-functions:0.3.0-dev-13' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0-dev-11") + implementation("space.kscience:kmath-functions:0.3.0-dev-13") } ``` diff --git a/kmath-kotlingrad/README.md b/kmath-kotlingrad/README.md index 4393cbf8c..31c7bb819 100644 --- a/kmath-kotlingrad/README.md +++ b/kmath-kotlingrad/README.md @@ -8,7 +8,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0-dev-11`. +The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0-dev-13`. **Gradle:** ```gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-kotlingrad:0.3.0-dev-11' + implementation 'space.kscience:kmath-kotlingrad:0.3.0-dev-13' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-kotlingrad:0.3.0-dev-11") + implementation("space.kscience:kmath-kotlingrad:0.3.0-dev-13") } ``` diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 6408be13b..1c945f06a 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-11`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-13`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0-dev-11' + implementation 'space.kscience:kmath-nd4j:0.3.0-dev-13' } ``` **Gradle Kotlin DSL:** @@ -30,7 +30,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0-dev-11") + implementation("space.kscience:kmath-nd4j:0.3.0-dev-13") } ``` diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 75de2bf35..dd21a9f2f 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -9,7 +9,7 @@ Common linear algebra operations on tensors. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-11`. +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-13`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensors:0.3.0-dev-11' + implementation 'space.kscience:kmath-tensors:0.3.0-dev-13' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensors:0.3.0-dev-11") + implementation("space.kscience:kmath-tensors:0.3.0-dev-13") } ``` From 46bf66c8ee28f6c3fa1645e19001b878cef60b7e Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Wed, 26 May 2021 20:24:29 +0700 Subject: [PATCH 379/393] Add justCalculate benchmark, some minor refactorings --- .../ExpressionsInterpretersBenchmark.kt | 46 ++++++++++++++--- .../space/kscience/kmath/ast/expressions.kt | 2 - kmath-ast/README.md | 15 +++--- kmath-ast/docs/README-TEMPLATE.md | 9 ++-- .../TestCompilerConsistencyWithInterpreter.kt | 4 +- .../kmath/ast/TestCompilerOperations.kt | 6 +-- .../kmath/ast/TestCompilerVariables.kt | 4 +- .../kmath/wasm/internal/WasmBuilder.kt | 6 +-- .../kscience/kmath/ast/TestExecutionTime.kt | 51 +++++++++++++++++-- .../kscience/kmath/wasm/TestWasmSpecific.kt | 4 +- .../kmath/asm/internal/codegenUtils.kt | 2 +- .../kmath/kotlingrad/AdaptingTests.kt | 7 ++- 12 files changed, 113 insertions(+), 43 deletions(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index 15cd14399..0294f924b 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -14,22 +14,51 @@ import space.kscience.kmath.expressions.* import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke +import kotlin.math.sin import kotlin.random.Random @State(Scope.Benchmark) internal class ExpressionsInterpretersBenchmark { + /** + * Benchmark case for [Expression] created with [expressionInExtendedField]. + */ @Benchmark fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole) + /** + * Benchmark case for [Expression] created with [toExpression]. + */ @Benchmark fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole) + /** + * Benchmark case for [Expression] created with [compileToExpression]. + */ @Benchmark fun asmExpression(blackhole: Blackhole) = invokeAndSum(asm, blackhole) + /** + * Benchmark case for [Expression] implemented manually with `kotlin.math` functions. + */ @Benchmark fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole) + /** + * Benchmark case for direct computation w/o [Expression]. + */ + @Benchmark + fun justCalculate(blackhole: Blackhole) { + val random = Random(0) + var sum = 0.0 + + repeat(times) { + val x = random.nextDouble() + sum += x * 2.0 + 2.0 / x - 16.0 / sin(x) + } + + blackhole.consume(sum) + } + private fun invokeAndSum(expr: Expression, blackhole: Blackhole) { val random = Random(0) var sum = 0.0 @@ -42,23 +71,24 @@ internal class ExpressionsInterpretersBenchmark { } private companion object { - private val x: Symbol by symbol - private val algebra: DoubleField = DoubleField + private val x by symbol + private val algebra = DoubleField private const val times = 1_000_000 - private val functional: Expression = DoubleField.expressionInExtendedField { + private val functional = DoubleField.expressionInExtendedField { bindSymbol(x) * number(2.0) + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x)) } private val node = MstExtendedField { - bindSymbol(x) * 2.0 + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x)) + x * 2.0 + number(2.0) / x - number(16.0) / sin(x) } - private val mst: Expression = node.toExpression(DoubleField) - private val asm: Expression = node.compileToExpression(DoubleField) + private val mst = node.toExpression(DoubleField) + private val asm = node.compileToExpression(DoubleField) - private val raw: Expression = Expression { args -> - args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 / kotlin.math.sin(args.getValue(x)) + private val raw = Expression { args -> + val x = args[x]!! + x * 2.0 + 2.0 / x - 16.0 / sin(x) } } } diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt index d5a82590f..96c9856cf 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt @@ -9,12 +9,10 @@ import space.kscience.kmath.expressions.MstField import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.interpret import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke fun main() { val expr = MstField { - val x = bindSymbol(x) x * 2.0 + number(2.0) / x - 16.0 } diff --git a/kmath-ast/README.md b/kmath-ast/README.md index b0f2d59e5..026c5a625 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -10,7 +10,7 @@ Performance and visualization extensions to MST API. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-11`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-13`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0-dev-11' + implementation 'space.kscience:kmath-ast:0.3.0-dev-13' } ``` **Gradle Kotlin DSL:** @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0-dev-11") + implementation("space.kscience:kmath-ast:0.3.0-dev-13") } ``` @@ -45,11 +45,12 @@ special implementation of `Expression` with implemented `invoke` function. For example, the following builder: ```kotlin +import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.* import space.kscience.kmath.operations.* import space.kscience.kmath.asm.* -MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) +MstField { x + 2 }.compileToExpression(DoubleField) ``` ... leads to generation of bytecode, which can be decompiled to the following Java class: @@ -89,11 +90,12 @@ public final class AsmCompiledExpression_45045_0 implements Expression { A similar feature is also available on JS. ```kotlin +import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.* import space.kscience.kmath.operations.* import space.kscience.kmath.estree.* -MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) +MstField { x + 2 }.compileToExpression(DoubleField) ``` The code above returns expression implemented with such a JS function: @@ -108,11 +110,12 @@ JS also supports very experimental expression optimization with [WebAssembly](ht Currently, only expressions inside `DoubleField` and `IntRing` are supported. ```kotlin +import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.* import space.kscience.kmath.operations.* import space.kscience.kmath.wasm.* -MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) +MstField { x + 2 }.compileToExpression(DoubleField) ``` An example of emitted Wasm IR in the form of WAT: diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index 80ea31642..b90f8ff08 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -16,11 +16,12 @@ special implementation of `Expression` with implemented `invoke` function. For example, the following builder: ```kotlin +import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.* import space.kscience.kmath.operations.* import space.kscience.kmath.asm.* -MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) +MstField { x + 2 }.compileToExpression(DoubleField) ``` ... leads to generation of bytecode, which can be decompiled to the following Java class: @@ -60,11 +61,12 @@ public final class AsmCompiledExpression_45045_0 implements Expression { A similar feature is also available on JS. ```kotlin +import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.* import space.kscience.kmath.operations.* import space.kscience.kmath.estree.* -MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) +MstField { x + 2 }.compileToExpression(DoubleField) ``` The code above returns expression implemented with such a JS function: @@ -79,11 +81,12 @@ JS also supports very experimental expression optimization with [WebAssembly](ht Currently, only expressions inside `DoubleField` and `IntRing` are supported. ```kotlin +import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.* import space.kscience.kmath.operations.* import space.kscience.kmath.wasm.* -MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField) +MstField { x + 2 }.compileToExpression(DoubleField) ``` An example of emitted Wasm IR in the form of WAT: diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt index 6209661b3..3116466e6 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt @@ -22,7 +22,7 @@ internal class TestCompilerConsistencyWithInterpreter { val mst = MstRing { binaryOperationFunction("+")( unaryOperationFunction("+")( - (bindSymbol(x) - (2.toByte() + (scale( + (x - (2.toByte() + (scale( add(number(1), number(1)), 2.0, ) + 1.toByte()))) * 3.0 - 1.toByte() @@ -42,7 +42,7 @@ internal class TestCompilerConsistencyWithInterpreter { fun doubleField() = runCompilerTest { val mst = MstField { +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( - (3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + (3.0 - (x + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0 + number(1), number(1) / 2 + number(2.0) * one, ) + zero diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt index 073a03f14..f869efd62 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt @@ -47,19 +47,19 @@ internal class TestCompilerOperations { @Test fun testSubtract() = runCompilerTest { - val expr = MstExtendedField { bindSymbol(x) - bindSymbol(x) }.compileToExpression(DoubleField) + val expr = MstExtendedField { x - x }.compileToExpression(DoubleField) assertEquals(0.0, expr(x to 2.0)) } @Test fun testDivide() = runCompilerTest { - val expr = MstExtendedField { bindSymbol(x) / bindSymbol(x) }.compileToExpression(DoubleField) + val expr = MstExtendedField { x / x }.compileToExpression(DoubleField) assertEquals(1.0, expr(x to 2.0)) } @Test fun testPower() = runCompilerTest { - val expr = MstExtendedField { bindSymbol(x) pow 2 }.compileToExpression(DoubleField) + val expr = MstExtendedField { x pow 2 }.compileToExpression(DoubleField) assertEquals(4.0, expr(x to 2.0)) } } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt index dcc15b311..bed5bc7fa 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt @@ -18,13 +18,13 @@ import kotlin.test.assertFailsWith internal class TestCompilerVariables { @Test fun testVariable() = runCompilerTest { - val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing) + val expr = MstRing { x }.compileToExpression(IntRing) assertEquals(1, expr(x to 1)) } @Test fun testUndefinedVariableFails() = runCompilerTest { - val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing) + val expr = MstRing { x }.compileToExpression(IntRing) assertFailsWith { expr() } } } diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt index 95ace1bad..c89ad83c4 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -27,11 +27,7 @@ internal sealed class WasmBuilder( lateinit var ctx: BinaryenModule open fun visitSymbolic(mst: Symbol): ExpressionRef { - try { - algebra.bindSymbol(mst) - } catch (ignored: Throwable) { - null - }?.let { return visitNumeric(Numeric(it)) } + algebra.bindSymbolOrNull(mst)?.let { return visitNumeric(Numeric(it)) } var idx = keys.indexOf(mst) diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt index 6cb378182..d0e8128b4 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/TestExecutionTime.kt @@ -7,7 +7,6 @@ package space.kscience.kmath.ast import space.kscience.kmath.expressions.* import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.math.sin @@ -17,18 +16,19 @@ import kotlin.time.measureTime import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression +// TODO move to benchmarks when https://github.com/Kotlin/kotlinx-benchmark/pull/38 or similar feature is merged internal class TestExecutionTime { private companion object { private const val times = 1_000_000 private val x by symbol - private val algebra: ExtendedField = DoubleField + private val algebra = DoubleField private val functional = DoubleField.expressionInExtendedField { bindSymbol(x) * const(2.0) + const(2.0) / bindSymbol(x) - const(16.0) / sin(bindSymbol(x)) } private val node = MstExtendedField { - bindSymbol(x) * number(2.0) + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x)) + x * number(2.0) + number(2.0) / x - number(16.0) / sin(x) } private val mst = node.toExpression(DoubleField) @@ -43,7 +43,13 @@ internal class TestExecutionTime { // }; private val raw = Expression { args -> - args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 / sin(args.getValue(x)) + val x = args[x]!! + x * 2.0 + 2.0 / x - 16.0 / sin(x) + } + + private val justCalculate = { args: dynamic -> + val x = args[x].unsafeCast() + x * 2.0 + 2.0 / x - 16.0 / sin(x) } } @@ -51,21 +57,56 @@ internal class TestExecutionTime { println(name) val rng = Random(0) var sum = 0.0 - measureTime { repeat(times) { sum += expr(x to rng.nextDouble()) } }.also(::println) + measureTime { + repeat(times) { sum += expr(x to rng.nextDouble()) } + }.also(::println) } + /** + * [Expression] created with [expressionInExtendedField]. + */ @Test fun functionalExpression() = invokeAndSum("functional", functional) + /** + * [Expression] created with [mstExpression]. + */ @Test fun mstExpression() = invokeAndSum("mst", mst) + /** + * [Expression] created with [wasmCompileToExpression]. + */ @Test fun wasmExpression() = invokeAndSum("wasm", wasm) + /** + * [Expression] created with [estreeCompileToExpression]. + */ @Test fun estreeExpression() = invokeAndSum("estree", wasm) + /** + * [Expression] implemented manually with `kotlin.math`. + */ @Test fun rawExpression() = invokeAndSum("raw", raw) + + /** + * Direct computation w/o [Expression]. + */ + @Test + fun justCalculateExpression() { + println("justCalculate") + val rng = Random(0) + var sum = 0.0 + measureTime { + repeat(times) { + val arg = rng.nextDouble() + val o = js("{}") + o["x"] = arg + sum += justCalculate(o) + } + }.also(::println) + } } diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt index abdf865c7..45776c191 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt @@ -31,7 +31,7 @@ internal class TestWasmSpecific { @Test fun argsPassing() { - val res = MstExtendedField { bindSymbol(y) + bindSymbol(x).pow(10) }.compile( + val res = MstExtendedField { y + x.pow(10) }.compile( DoubleField, x to 2.0, y to 100000000.0, @@ -42,7 +42,7 @@ internal class TestWasmSpecific { @Test fun powFunction() { - val expr = MstExtendedField { bindSymbol(x).pow(1.0 / 6.0) }.compileToExpression(DoubleField) + val expr = MstExtendedField { x.pow(1.0 / 6.0) }.compileToExpression(DoubleField) assertEquals(0.9730585187140817, expr(x to 0.8488554755054833)) } diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt index cfac59847..a84248f63 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt @@ -63,7 +63,7 @@ internal fun MethodVisitor.label(): Label = Label().also(::visitLabel) * @author Iaroslav Postovalov */ internal tailrec fun buildName(mst: MST, collision: Int = 0): String { - val name = "kscience.kmath.asm.generated.AsmCompiledExpression_${mst.hashCode()}_$collision" + val name = "space.kscience.kmath.asm.generated.AsmCompiledExpression_${mst.hashCode()}_$collision" try { Class.forName(name) diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index 57fe2411c..9378adfea 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -20,8 +20,7 @@ import kotlin.test.fail internal class AdaptingTests { @Test fun symbol() { - val c1 = MstNumericAlgebra.bindSymbol(x.identity) - assertEquals(x.identity, c1.toSVar>().name) + assertEquals(x.identity, x.toSVar>().name) val c2 = "kitten".parseMath().toSFun>() if (c2 is SVar) assertTrue(c2.name == "kitten") else fail() } @@ -46,7 +45,7 @@ internal class AdaptingTests { @Test fun simpleFunctionDerivative() { - val xSVar = MstNumericAlgebra.bindSymbol(x.identity).toSVar>() + val xSVar = x.toSVar>() val quadratic = "x^2-4*x-44".parseMath().toSFun>() val actualDerivative = quadratic.d(xSVar).toMst().compileToExpression(DoubleField) val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField) @@ -55,7 +54,7 @@ internal class AdaptingTests { @Test fun moreComplexDerivative() { - val xSVar = MstNumericAlgebra.bindSymbol(x.identity).toSVar>() + val xSVar = x.toSVar>() val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun>() val actualDerivative = composition.d(xSVar).toMst().compileToExpression(DoubleField) From 2dff15c5aa2afe2ce99edfe8ae0fe4dc1db64087 Mon Sep 17 00:00:00 2001 From: therealansh Date: Thu, 3 Jun 2021 01:14:19 +0530 Subject: [PATCH 380/393] integrate: Jafama + KMath --- kmath-jafama/build.gradle.kts | 21 + .../kscience/kmath/jafama/CmnFastMath.java | 2112 ++++++++++++ .../kscience/kmath/jafama/DoubleWrapper.java | 13 + .../space/kscience/kmath/jafama/FastMath.java | 2986 ++++++++++++++++ .../kscience/kmath/jafama/IntWrapper.java | 13 + .../kscience/kmath/jafama/KMathJafama.kt | 102 + .../kscience/kmath/jafama/NumbersUtils.java | 2647 +++++++++++++++ .../kscience/kmath/jafama/StrictFastMath.java | 2998 +++++++++++++++++ settings.gradle.kts | 1 + 9 files changed, 10893 insertions(+) create mode 100644 kmath-jafama/build.gradle.kts create mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/CmnFastMath.java create mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/DoubleWrapper.java create mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/FastMath.java create mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/IntWrapper.java create mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt create mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/NumbersUtils.java create mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/StrictFastMath.java diff --git a/kmath-jafama/build.gradle.kts b/kmath-jafama/build.gradle.kts new file mode 100644 index 000000000..22d50f89c --- /dev/null +++ b/kmath-jafama/build.gradle.kts @@ -0,0 +1,21 @@ +plugins { + id("ru.mipt.npm.gradle.jvm") +} + +dependencies { + api(project(":kmath-ast")) + api(project(":kmath-complex")) + api(project(":kmath-for-real")) +} + +kscience{ + useHtml() +} + +readme { + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE +} + +kotlin.sourceSets.all { + languageSettings.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI") +} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/CmnFastMath.java b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/CmnFastMath.java new file mode 100644 index 000000000..0abc5d95d --- /dev/null +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/CmnFastMath.java @@ -0,0 +1,2112 @@ +/* + * 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.jafama; + +/** + * Stuffs for FastMath and StrictFastMath. + */ +abstract class CmnFastMath { + + /* + * For trigonometric functions, use of look-up tables and Taylor-Lagrange formula + * with 4 derivatives (more take longer to compute and don't add much accuracy, + * less require larger tables (which use more memory, take more time to initialize, + * and are slower to access (at least on the machine they were developed on))). + * + * For angles reduction of cos/sin/tan functions: + * - for small values, instead of reducing angles, and then computing the best index + * for look-up tables, we compute this index right away, and use it for reduction, + * - for large values, treatments derived from fdlibm package are used, as done in + * java.lang.Math. They are faster but still "slow", so if you work with + * large numbers and need speed over accuracy for them, you might want to use + * normalizeXXXFast treatments before your function, or modify cos/sin/tan + * so that they call the fast normalization treatments instead of the accurate ones. + * NB: If an angle is huge (like PI*1e20), in double precision format its last digits + * are zeros, which most likely is not the case for the intended value, and doing + * an accurate reduction on a very inaccurate value is most likely pointless. + * But it gives some sort of coherence that could be needed in some cases. + * + * Multiplication on double appears to be about as fast (or not much slower) than call + * to [], and regrouping some doubles in a private class, to use + * index only once, does not seem to speed things up, so: + * - for uniformly tabulated values, to retrieve the parameter corresponding to + * an index, we recompute it rather than using an array to store it, + * - for cos/sin, we recompute derivatives divided by (multiplied by inverse of) + * factorial each time, rather than storing them in arrays. + * + * Lengths of look-up tables are usually of the form 2^n+1, for their values to be + * of the form ( * k/2^n, k in 0 .. 2^n), so that particular values + * (PI/2, etc.) are "exactly" computed, as well as for other reasons. + * + * Tables are put in specific inner classes, to be lazily initialized. + * Always doing strict tables initialization, even if StrictFastMath delegates + * to StrictMath and doesn't use tables, which makes tables initialization a bit + * slower but code simpler. + * Using redefined pure Java treatments during tables initialization, + * instead of Math or StrictMath ones (even asin(double)), can be very slow, + * because class loading is likely not to be optimized. + * + * Most math treatments I could find on the web, including "fast" ones, + * usually take care of special cases (NaN, etc.) at the beginning, and + * then deal with the general case, which adds a useless overhead for the + * general (and common) case. In this class, special cases are only dealt + * with when needed, and if the general case does not already handle them. + */ + + /* + * Regarding strictfp-ness: + * + * Switching from/to strictfp has some overhead, so we try to only + * strictfp-ize when needed (or when clueless). + * Compile-time constants are computed in a FP-strict way, so no need + * to make this whole class strictfp. + */ + + //-------------------------------------------------------------------------- + // CONFIGURATION + //-------------------------------------------------------------------------- + + /* + * FastMath + */ + + static final boolean FM_USE_JDK_MATH = getBooleanProperty("jafama.usejdk", false); + + /** + * Used for both FastMath.log(double) and FastMath.log10(double). + */ + static final boolean FM_USE_REDEFINED_LOG = getBooleanProperty("jafama.fastlog", false); + + static final boolean FM_USE_REDEFINED_SQRT = getBooleanProperty("jafama.fastsqrt", false); + + /** + * Set it to true if FastMath.sqrt(double) is slow + * (more tables, but less calls to FastMath.sqrt(double)). + */ + static final boolean FM_USE_POWTABS_FOR_ASIN = false; + + /* + * StrictFastMath + */ + + static final boolean SFM_USE_JDK_MATH = getBooleanProperty("jafama.strict.usejdk", false); + + /** + * Used for both StrictFastMath.log(double) and StrictFastMath.log10(double). + * True by default because the StrictMath implementations can be slow. + */ + static final boolean SFM_USE_REDEFINED_LOG = getBooleanProperty("jafama.strict.fastlog", true); + + static final boolean SFM_USE_REDEFINED_SQRT = getBooleanProperty("jafama.strict.fastsqrt", false); + + /** + * Set it to true if StrictFastMath.sqrt(double) is slow + * (more tables, but less calls to StrictFastMath.sqrt(double)). + */ + static final boolean SFM_USE_POWTABS_FOR_ASIN = false; + + /* + * Common to FastMath and StrictFastMath. + */ + + /** + * Using two pow tab can just make things barely faster, + * and could relatively hurt in case of cache-misses, + * especially for methods that otherwise wouldn't rely + * on any tab, so we don't use it. + */ + static final boolean USE_TWO_POW_TAB = false; + + /** + * Because on some architectures, some casts can be slow, + * especially for large values. + * Might make things a bit slower for latest architectures, + * but not as much as it makes them faster for older ones. + */ + static final boolean ANTI_SLOW_CASTS = true; + + /** + * If some methods get JIT-optimized, they might crash + * if they contain "(var == xxx)" with var being NaN + * (can happen with Java 6u29). + * + * The crash does not happen if we replace "==" with "<" or ">". + * + * Only the code that has been observed to trigger the bug + * has been modified. + */ + static final boolean ANTI_JIT_OPTIM_CRASH_ON_NAN = true; + + //-------------------------------------------------------------------------- + // GENERAL CONSTANTS + //-------------------------------------------------------------------------- + + /** + * Closest double approximation of e. + */ + public static final double E = Math.E; + + /** + * Closest double approximation of pi, which is inferior to mathematical pi: + * pi ~= 3.14159265358979323846... + * PI ~= 3.141592653589793 + */ + public static final double PI = Math.PI; + + /** + * High double approximation of pi, which is further from pi + * than the low approximation PI: + * pi ~= 3.14159265358979323846... + * PI ~= 3.141592653589793 + * PI_SUP ~= 3.1415926535897936 + */ + public static final double PI_SUP = Double.longBitsToDouble(Double.doubleToRawLongBits(Math.PI)+1); + + static final double ONE_DIV_F2 = 1/2.0; + static final double ONE_DIV_F3 = 1/6.0; + static final double ONE_DIV_F4 = 1/24.0; + + static final float TWO_POW_23_F = (float)NumbersUtils.twoPow(23); + + static final double TWO_POW_24 = NumbersUtils.twoPow(24); + private static final double TWO_POW_N24 = NumbersUtils.twoPow(-24); + + static final double TWO_POW_26 = NumbersUtils.twoPow(26); + static final double TWO_POW_N26 = NumbersUtils.twoPow(-26); + + // First double value (from zero) such as (value+-1/value == value). + static final double TWO_POW_27 = NumbersUtils.twoPow(27); + static final double TWO_POW_N27 = NumbersUtils.twoPow(-27); + + static final double TWO_POW_N28 = NumbersUtils.twoPow(-28); + + static final double TWO_POW_52 = NumbersUtils.twoPow(52); + + static final double TWO_POW_N55 = NumbersUtils.twoPow(-55); + + static final double TWO_POW_66 = NumbersUtils.twoPow(66); + + static final double TWO_POW_512 = NumbersUtils.twoPow(512); + static final double TWO_POW_N512 = NumbersUtils.twoPow(-512); + + /** + * Double.MIN_NORMAL since Java 6. + */ + static final double DOUBLE_MIN_NORMAL = Double.longBitsToDouble(0x0010000000000000L); // 2.2250738585072014E-308 + + // Not storing float/double mantissa size in constants, + // for 23 and 52 are shorter to read and more + // bitwise-explicit than some constant's name. + + static final int MIN_DOUBLE_EXPONENT = -1074; + static final int MIN_DOUBLE_NORMAL_EXPONENT = -1022; + static final int MAX_DOUBLE_EXPONENT = 1023; + + static final int MIN_FLOAT_NORMAL_EXPONENT = -126; + static final int MAX_FLOAT_EXPONENT = 127; + + private static final double SQRT_2 = StrictMath.sqrt(2.0); + + static final double LOG_2 = StrictMath.log(2.0); + static final double LOG_TWO_POW_27 = StrictMath.log(TWO_POW_27); + static final double LOG_DOUBLE_MAX_VALUE = StrictMath.log(Double.MAX_VALUE); + + static final double INV_LOG_10 = 1.0/StrictMath.log(10.0); + + static final double DOUBLE_BEFORE_60 = Double.longBitsToDouble(Double.doubleToRawLongBits(60.0)-1); + + //-------------------------------------------------------------------------- + // CONSTANTS FOR NORMALIZATIONS + //-------------------------------------------------------------------------- + + /** + * Table of constants for 1/(PI/2), 282 Hex digits (enough for normalizing doubles). + * 1/(PI/2) approximation = sum of TWO_OVER_PI_TAB[i]*2^(-24*(i+1)). + * + * double and not int, to avoid int-to-double cast during computations. + */ + private static final double TWO_OVER_PI_TAB[] = { + 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, + 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, + 0x424DD2, 0xe00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, + 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, + 0x3991d6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, + 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, + 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, + 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, + 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, + 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, + 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B}; + + /* + * Constants for PI/2. Only the 23 most significant bits of each mantissa are used. + * 2*PI approximation = sum of TWOPI_TAB. + */ + private static final double PIO2_TAB0 = Double.longBitsToDouble(0x3FF921FB40000000L); + private static final double PIO2_TAB1 = Double.longBitsToDouble(0x3E74442D00000000L); + private static final double PIO2_TAB2 = Double.longBitsToDouble(0x3CF8469880000000L); + private static final double PIO2_TAB3 = Double.longBitsToDouble(0x3B78CC5160000000L); + private static final double PIO2_TAB4 = Double.longBitsToDouble(0x39F01B8380000000L); + private static final double PIO2_TAB5 = Double.longBitsToDouble(0x387A252040000000L); + + static final double PIO2_INV = Double.longBitsToDouble(0x3FE45F306DC9C883L); // 6.36619772367581382433e-01 53 bits of 2/pi + static final double PIO2_HI = Double.longBitsToDouble(0x3FF921FB54400000L); // 1.57079632673412561417e+00 first 33 bits of pi/2 + static final double PIO2_LO = Double.longBitsToDouble(0x3DD0B4611A626331L); // 6.07710050650619224932e-11 pi/2 - PIO2_HI + static final double PI_INV = PIO2_INV/2; + static final double PI_HI = 2*PIO2_HI; + static final double PI_LO = 2*PIO2_LO; + static final double TWOPI_INV = PIO2_INV/4; + static final double TWOPI_HI = 4*PIO2_HI; + static final double TWOPI_LO = 4*PIO2_LO; + + /** + * Bit = 0 where quadrant is encoded in remainder bits. + */ + private static final long QUADRANT_BITS_0_MASK = 0xCFFFFFFFFFFFFFFFL; + + /** + * Remainder bits where quadrant is encoded, 0 elsewhere. + */ + private static final long QUADRANT_PLACE_BITS = 0x3000000000000000L; + + /** + * fdlibm uses 2^19*PI/2 here. + * With 2^18*PI/2 we would be more accurate, for example when normalizing + * 822245.903631403, which is close to 2^19*PI/2, but we are still in + * our accuracy tolerance with fdlibm's value (but not 2^20*PI/2) so we + * stick to it, to help being faster than (Strict)Math for values in + * [2^18*PI/2,2^19*PI/2]. + * + * For tests, can use a smaller value, for heavy remainder + * not to only be used with huge values. + */ + static final double NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2 = StrictMath.pow(2.0,19.0)*(Math.PI/2); + + /** + * 2*Math.PI, normalized into [-PI,PI], as returned by + * StrictMath.asin(StrictMath.sin(2*Math.PI)) + * (asin behaves as identity for this). + * + * NB: NumbersUtils.minus2PI(2*Math.PI) returns -2.449293598153844E-16, + * which is different due to not using an accurate enough definition of PI. + */ + static final double TWO_MATH_PI_IN_MINUS_PI_PI = -2.4492935982947064E-16; + + //-------------------------------------------------------------------------- + // CONSTANTS AND TABLES FOR SIN AND COS + //-------------------------------------------------------------------------- + + static final int SIN_COS_TABS_SIZE = (1<>9) / SIN_COS_INDEXER) * 0.99; + + //-------------------------------------------------------------------------- + // CONSTANTS AND TABLES FOR TAN + //-------------------------------------------------------------------------- + + // We use the following formula: + // 1) tan(-x) = -tan(x) + // 2) tan(x) = 1/tan(PI/2-x) + // ---> we only have to compute tan(x) on [0,A] with PI/4<=A= 45deg, and supposed to be >= 51.4deg, as fdlibm code is not + * supposed to work with values inferior to that (51.4deg is about + * (PI/2-Double.longBitsToDouble(0x3FE5942800000000L))). + */ + static final double TAN_MAX_VALUE_FOR_TABS = StrictMath.toRadians(77.0); + + static final int TAN_TABS_SIZE = (int)((TAN_MAX_VALUE_FOR_TABS/(Math.PI/2)) * (TAN_VIRTUAL_TABS_SIZE-1)) + 1; + static final double TAN_DELTA_HI = PIO2_HI/(TAN_VIRTUAL_TABS_SIZE-1); + static final double TAN_DELTA_LO = PIO2_LO/(TAN_VIRTUAL_TABS_SIZE-1); + static final double TAN_INDEXER = 1/(TAN_DELTA_HI+TAN_DELTA_LO); + + static final class MyTTan { + static final double[] tanTab = new double[TAN_TABS_SIZE]; + static final double[] tanDer1DivF1Tab = new double[TAN_TABS_SIZE]; + static final double[] tanDer2DivF2Tab = new double[TAN_TABS_SIZE]; + static final double[] tanDer3DivF3Tab = new double[TAN_TABS_SIZE]; + static final double[] tanDer4DivF4Tab = new double[TAN_TABS_SIZE]; + static { + init(); + } + private static strictfp void init() { + for (int i=0;i>9) / TAN_INDEXER) * 0.99); + + //-------------------------------------------------------------------------- + // CONSTANTS AND TABLES FOR ACOS, ASIN + //-------------------------------------------------------------------------- + + // We use the following formula: + // 1) acos(x) = PI/2 - asin(x) + // 2) asin(-x) = -asin(x) + // ---> we only have to compute asin(x) on [0,1]. + // For values not close to +-1, we use look-up tables; + // for values near +-1, we use code derived from fdlibm. + + /** + * Supposed to be >= sin(77.2deg), as fdlibm code is supposed to work with values > 0.975, + * but seems to work well enough as long as value >= sin(25deg). + */ + static final double ASIN_MAX_VALUE_FOR_TABS = StrictMath.sin(StrictMath.toRadians(73.0)); + + static final int ASIN_TABS_SIZE = (1< we only have to compute atan(x) on [0,+Infinity[. + // For values corresponding to angles not close to +-PI/2, we use look-up tables; + // for values corresponding to angles near +-PI/2, we use code derived from fdlibm. + + /** + * Supposed to be >= tan(67.7deg), as fdlibm code is supposed to work with values > 2.4375. + */ + static final double ATAN_MAX_VALUE_FOR_TABS = StrictMath.tan(StrictMath.toRadians(74.0)); + + static final int ATAN_TABS_SIZE = (1<>SQRT_LO_BITS)); + for (int i=1;i>CBRT_LO_BITS)); + for (int i=1;i= MIN_DOUBLE_EXPONENT) { + if (power <= MAX_DOUBLE_EXPONENT) { // Normal or subnormal. + return MyTTwoPow.twoPowTab[power-MIN_DOUBLE_EXPONENT]; + } else { // Overflow. + return Double.POSITIVE_INFINITY; + } + } else { // Underflow. + return 0.0; + } + } else { + return NumbersUtils.twoPow(power); + } + } + + /** + * @param value An int value. + * @return value*value. + */ + public static int pow2(int value) { + return value*value; + } + + /** + * @param value A long value. + * @return value*value. + */ + public static long pow2(long value) { + return value*value; + } + + /** + * @param value An int value. + * @return value*value*value. + */ + public static int pow3(int value) { + return value*value*value; + } + + /** + * @param value A long value. + * @return value*value*value. + */ + public static long pow3(long value) { + return value*value*value; + } + + /* + * absolute values + */ + + /** + * @param value An int value. + * @return The absolute value, except if value is Integer.MIN_VALUE, for which it returns Integer.MIN_VALUE. + */ + public static int abs(int value) { + if (FM_USE_JDK_MATH || SFM_USE_JDK_MATH) { + return Math.abs(value); + } + return NumbersUtils.abs(value); + } + + /** + * @param value A long value. + * @return The absolute value, except if value is Long.MIN_VALUE, for which it returns Long.MIN_VALUE. + */ + public static long abs(long value) { + if (FM_USE_JDK_MATH || SFM_USE_JDK_MATH) { + return Math.abs(value); + } + return NumbersUtils.abs(value); + } + + /* + * close values + */ + + /** + * @param value A long value. + * @return The specified value as int. + * @throws ArithmeticException if the specified value is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. + */ + public static int toIntExact(long value) { + return NumbersUtils.asInt(value); + } + + /** + * @param value A long value. + * @return The closest int value in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. + */ + public static int toInt(long value) { + return NumbersUtils.toInt(value); + } + + /* + * ranges + */ + + /** + * @param min An int value. + * @param max An int value. + * @param value An int value. + * @return minValue if value < minValue, maxValue if value > maxValue, value otherwise. + */ + public static int toRange(int min, int max, int value) { + return NumbersUtils.toRange(min, max, value); + } + + /** + * @param min A long value. + * @param max A long value. + * @param value A long value. + * @return min if value < min, max if value > max, value otherwise. + */ + public static long toRange(long min, long max, long value) { + return NumbersUtils.toRange(min, max, value); + } + + /* + * unary operators (increment,decrement,negate) + */ + + /** + * @param value An int value. + * @return The argument incremented by one. + * @throws ArithmeticException if the mathematical result + * is not in int range. + */ + public static int incrementExact(int value) { + if (value == Integer.MAX_VALUE) { + throw new ArithmeticException("integer overflow"); + } + return value + 1; + } + + /** + * @param value A long value. + * @return The argument incremented by one. + * @throws ArithmeticException if the mathematical result + * is not in long range. + */ + public static long incrementExact(long value) { + if (value == Long.MAX_VALUE) { + throw new ArithmeticException("long overflow"); + } + return value + 1L; + } + + /** + * @param value An int value. + * @return The argument incremented by one, or the argument + * if the mathematical result is not in int range. + */ + public static int incrementBounded(int value) { + if (value == Integer.MAX_VALUE) { + return value; + } + return value + 1; + } + + /** + * @param value A long value. + * @return The argument incremented by one, or the argument + * if the mathematical result is not in long range. + */ + public static long incrementBounded(long value) { + if (value == Long.MAX_VALUE) { + return value; + } + return value + 1L; + } + + /** + * @param value An int value. + * @return The argument decremented by one. + * @throws ArithmeticException if the mathematical result + * is not in int range. + */ + public static int decrementExact(int value) { + if (value == Integer.MIN_VALUE) { + throw new ArithmeticException("integer overflow"); + } + return value - 1; + } + + /** + * @param value A long value. + * @return The argument decremented by one. + * @throws ArithmeticException if the mathematical result + * is not in long range. + */ + public static long decrementExact(long value) { + if (value == Long.MIN_VALUE) { + throw new ArithmeticException("long overflow"); + } + return value - 1L; + } + + /** + * @param value An int value. + * @return The argument decremented by one, or the argument + * if the mathematical result is not in int range. + */ + public static int decrementBounded(int value) { + if (value == Integer.MIN_VALUE) { + return value; + } + return value - 1; + } + + /** + * @param value A long value. + * @return The argument decremented by one, or the argument + * if the mathematical result is not in long range. + */ + public static long decrementBounded(long value) { + if (value == Long.MIN_VALUE) { + return value; + } + return value - 1L; + } + + /** + * @param value An int value. + * @return The argument negated. + * @throws ArithmeticException if the mathematical result + * is not in int range. + */ + public static int negateExact(int value) { + if (value == Integer.MIN_VALUE) { + throw new ArithmeticException("integer overflow"); + } + return -value; + } + + /** + * @param value A long value. + * @return The argument negated. + * @throws ArithmeticException if the mathematical result + * is not in long range. + */ + public static long negateExact(long value) { + if (value == Long.MIN_VALUE) { + throw new ArithmeticException("long overflow"); + } + return -value; + } + + /** + * @param value An int value. + * @return The argument negated, or Integer.MAX_VALUE + * if the argument is Integer.MIN_VALUE. + */ + public static int negateBounded(int value) { + if (value == Integer.MIN_VALUE) { + return Integer.MAX_VALUE; + } + return -value; + } + + /** + * @param value A long value. + * @return The argument negated, or Long.MAX_VALUE + * if the argument is Long.MIN_VALUE. + */ + public static long negateBounded(long value) { + if (value == Long.MIN_VALUE) { + return Long.MAX_VALUE; + } + return -value; + } + + /* + * binary operators (+,-,*) + */ + + /** + * @param a An int value. + * @param b An int value. + * @return The mathematical result of a+b. + * @throws ArithmeticException if the mathematical result of a+b is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. + */ + public static int addExact(int a, int b) { + return NumbersUtils.plusExact(a, b); + } + + /** + * @param a A long value. + * @param b A long value. + * @return The mathematical result of a+b. + * @throws ArithmeticException if the mathematical result of a+b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. + */ + public static long addExact(long a, long b) { + return NumbersUtils.plusExact(a, b); + } + + /** + * @param a An int value. + * @param b An int value. + * @return The int value of [Integer.MIN_VALUE,Integer.MAX_VALUE] range which is the closest to mathematical result of a+b. + */ + public static int addBounded(int a, int b) { + return NumbersUtils.plusBounded(a, b); + } + + /** + * @param a A long value. + * @param b A long value. + * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a+b. + */ + public static long addBounded(long a, long b) { + return NumbersUtils.plusBounded(a, b); + } + + /** + * @param a An int value. + * @param b An int value. + * @return The mathematical result of a-b. + * @throws ArithmeticException if the mathematical result of a-b is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. + */ + public static int subtractExact(int a, int b) { + return NumbersUtils.minusExact(a, b); + } + + /** + * @param a A long value. + * @param b A long value. + * @return The mathematical result of a-b. + * @throws ArithmeticException if the mathematical result of a-b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. + */ + public static long subtractExact(long a, long b) { + return NumbersUtils.minusExact(a, b); + } + + /** + * @param a An int value. + * @param b An int value. + * @return The int value of [Integer.MIN_VALUE,Integer.MAX_VALUE] range which is the closest to mathematical result of a-b. + */ + public static int subtractBounded(int a, int b) { + return NumbersUtils.minusBounded(a, b); + } + + /** + * @param a A long value. + * @param b A long value. + * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a-b. + */ + public static long subtractBounded(long a, long b) { + return NumbersUtils.minusBounded(a, b); + } + + /** + * @param a An int value. + * @param b An int value. + * @return The mathematical result of a*b. + * @throws ArithmeticException if the mathematical result of a*b is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. + */ + public static int multiplyExact(int a, int b) { + return NumbersUtils.timesExact(a, b); + } + + /** + * @param a A long value. + * @param b An int value. + * @return The mathematical result of a*b. + * @throws ArithmeticException if the mathematical result of a*b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. + */ + public static long multiplyExact(long a, int b) { + return NumbersUtils.timesExact(a, (long) b); + } + + /** + * @param a A long value. + * @param b A long value. + * @return The mathematical result of a*b. + * @throws ArithmeticException if the mathematical result of a*b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. + */ + public static long multiplyExact(long a, long b) { + return NumbersUtils.timesExact(a, b); + } + + /** + * @param a An int value. + * @param b An int value. + * @return The int value of [Integer.MIN_VALUE,Integer.MAX_VALUE] range which is the closest to mathematical result of a*b. + */ + public static int multiplyBounded(int a, int b) { + return NumbersUtils.timesBounded(a, b); + } + + /** + * @param a A long value. + * @param b An int value. + * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a*b. + */ + public static long multiplyBounded(long a, int b) { + return NumbersUtils.timesBounded(a, (long) b); + } + + /** + * @param a A long value. + * @param b A long value. + * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a*b. + */ + public static long multiplyBounded(long a, long b) { + return NumbersUtils.timesBounded(a, b); + } + + /** + * @param x An int value. + * @param y An int value. + * @return The mathematical product as a long. + */ + public static long multiplyFull(int x, int y) { + return ((long) x) * ((long) y); + } + + /** + * @param x A long value. + * @param y A long value. + * @return The most significant 64 bits of the 128-bit product of two 64-bit factors. + */ + public static long multiplyHigh(long x, long y) { + if ((x|y) < 0) { + // Use technique from section 8-2 of Henry S. Warren, Jr., + // Hacker's Delight (2nd ed.) (Addison Wesley, 2013), 173-174. + long x1 = (x >> 32); + long y1 = (y >> 32); + long x2 = (x & 0xFFFFFFFFL); + long y2 = (y & 0xFFFFFFFFL); + long z2 = x2 * y2; + long t = x1 * y2 + (z2 >>> 32); + long z1 = (t & 0xFFFFFFFFL) + x2 * y1; + long z0 = (t >> 32); + return x1 * y1 + z0 + (z1 >> 32); + } else { + // Use Karatsuba technique with two base 2^32 digits. + long x1 = (x >>> 32); + long y1 = (y >>> 32); + long x2 = (x & 0xFFFFFFFFL); + long y2 = (y & 0xFFFFFFFFL); + long A = x1 * y1; + long B = x2 * y2; + long C = (x1 + x2) * (y1 + y2); + long K = C - A - B; + return (((B >>> 32) + K) >>> 32) + A; + } + } + + /* + * binary operators (/,%) + */ + + /** + * Returns the largest int <= dividend/divisor. + * + * Unlike "/" operator, which rounds towards 0, this division + * rounds towards -Infinity (which give different result + * when the exact result is negative). + * + * @param x The dividend. + * @param y The divisor. + * @return The largest int <= dividend/divisor, unless dividend is + * Integer.MIN_VALUE and divisor is -1, in which case + * Integer.MIN_VALUE is returned. + * @throws ArithmeticException if the divisor is zero. + */ + public static int floorDiv(int x, int y) { + int r = x / y; + // If the signs are different and modulo not zero, rounding down. + if (((x ^ y) < 0) && ((r * y) != x)) { + r--; + } + return r; + } + + /** + * Returns the largest long <= dividend/divisor. + * + * Unlike "/" operator, which rounds towards 0, this division + * rounds towards -Infinity (which give different result + * when the exact result is negative). + * + * @param x The dividend. + * @param y The divisor. + * @return The largest long <= dividend/divisor, unless dividend is + * Long.MIN_VALUE and divisor is -1, in which case + * Long.MIN_VALUE is returned. + * @throws ArithmeticException if the divisor is zero. + */ + public static long floorDiv(long x, int y) { + return floorDiv(x, (long) y); + } + + /** + * Returns the largest long <= dividend/divisor. + * + * Unlike "/" operator, which rounds towards 0, this division + * rounds towards -Infinity (which give different result + * when the exact result is negative). + * + * @param x The dividend. + * @param y The divisor. + * @return The largest long <= dividend/divisor, unless dividend is + * Long.MIN_VALUE and divisor is -1, in which case + * Long.MIN_VALUE is returned. + * @throws ArithmeticException if the divisor is zero. + */ + public static long floorDiv(long x, long y) { + long r = x / y; + // If the signs are different and modulo not zero, rounding down. + if (((x ^ y) < 0) && ((r * y) != x)) { + r--; + } + return r; + } + + /** + * Returns the floor modulus, which is "x - floorDiv(x,y) * y", + * has the same sign as y, and is in ]-abs(y),abs(y)[. + * + * The relationship between floorMod and floorDiv is the same + * than between "%" and "/". + * + * @param x The dividend. + * @param y The divisor. + * @return The floor modulus, i.e. "x - (floorDiv(x, y) * y)". + * @throws ArithmeticException if the divisor is zero. + */ + public static int floorMod(int x, int y) { + return x - floorDiv(x, y) * y; + } + + /** + * Returns the floor modulus, which is "x - floorDiv(x,y) * y", + * has the same sign as y, and is in ]-abs(y),abs(y)[. + * + * The relationship between floorMod and floorDiv is the same + * than between "%" and "/". + * + * @param x The dividend. + * @param y The divisor. + * @return The floor modulus, i.e. "x - (floorDiv(x, y) * y)". + * @throws ArithmeticException if the divisor is zero. + */ + public static int floorMod(long x, int y) { + // No overflow so can cast. + return (int) (x - floorDiv(x,y) * y); + } + + /** + * Returns the floor modulus, which is "x - floorDiv(x,y) * y", + * has the same sign as y, and is in ]-abs(y),abs(y)[. + * + * The relationship between floorMod and floorDiv is the same + * than between "%" and "/". + * + * @param x The dividend. + * @param y The divisor. + * @return The floor modulus, i.e. "x - (floorDiv(x, y) * y)". + * @throws ArithmeticException if the divisor is zero. + */ + public static long floorMod(long x, long y) { + return x - floorDiv(x, y) * y; + } + + /* + * Non-redefined Math public values and treatments. + */ + + public static int min(int a, int b) { + return Math.min(a,b); + } + + public static long min(long a, long b) { + return Math.min(a,b); + } + + public static int max(int a, int b) { + return Math.max(a,b); + } + + public static long max(long a, long b) { + return Math.max(a,b); + } + + //-------------------------------------------------------------------------- + // PACKAGE-PRIVATE METHODS + //-------------------------------------------------------------------------- + + /** + * @param power Must be in normal values range. + */ + static double twoPowNormal(int power) { + if (USE_TWO_POW_TAB) { + return MyTTwoPow.twoPowTab[power-MIN_DOUBLE_EXPONENT]; + } else { + return Double.longBitsToDouble(((long)(power+MAX_DOUBLE_EXPONENT))<<52); + } + } + + /** + * @param power Must be in normal or subnormal values range. + */ + static double twoPowNormalOrSubnormal(int power) { + if (USE_TWO_POW_TAB) { + return MyTTwoPow.twoPowTab[power-MIN_DOUBLE_EXPONENT]; + } else { + if (power <= -MAX_DOUBLE_EXPONENT) { // Not normal. + return Double.longBitsToDouble(0x0008000000000000L>>(-(power+MAX_DOUBLE_EXPONENT))); + } else { // Normal. + return Double.longBitsToDouble(((long)(power+MAX_DOUBLE_EXPONENT))<<52); + } + } + } + + static double atan2_pinf_yyy(double y) { + if (y == Double.POSITIVE_INFINITY) { + return Math.PI/4; + } else if (y == Double.NEGATIVE_INFINITY) { + return -Math.PI/4; + } else if (y > 0.0) { + return 0.0; + } else if (y < 0.0) { + return -0.0; + } else { + return Double.NaN; + } + } + + static double atan2_ninf_yyy(double y) { + if (y == Double.POSITIVE_INFINITY) { + return 3*Math.PI/4; + } else if (y == Double.NEGATIVE_INFINITY) { + return -3*Math.PI/4; + } else if (y > 0.0) { + return Math.PI; + } else if (y < 0.0) { + return -Math.PI; + } else { + return Double.NaN; + } + } + + static double atan2_yyy_zeroOrNaN(double y, double x) { + if (x == 0.0) { + if (y == 0.0) { + if (signFromBit_antiCyclic(x) < 0) { + // x is -0.0 + return signFromBit_antiCyclic(y) * Math.PI; + } else { + // +-0.0 + return y; + } + } + if (y > 0.0) { + return Math.PI/2; + } else if (y < 0.0) { + return -Math.PI/2; + } else { + return Double.NaN; + } + } else { + return Double.NaN; + } + } + + /** + * At least one of the arguments must be NaN. + */ + static double hypot_NaN(double xAbs, double yAbs) { + if ((xAbs == Double.POSITIVE_INFINITY) || (yAbs == Double.POSITIVE_INFINITY)) { + return Double.POSITIVE_INFINITY; + } else { + return Double.NaN; + } + } + + /** + * At least one of the arguments must be NaN. + */ + static double hypot_NaN(double xAbs, double yAbs, double zAbs) { + if ((xAbs == Double.POSITIVE_INFINITY) || (yAbs == Double.POSITIVE_INFINITY) || (zAbs == Double.POSITIVE_INFINITY)) { + return Double.POSITIVE_INFINITY; + } else { + return Double.NaN; + } + } + + /* + * + */ + + /** + * @param remainder Must have 1 for 2nd and 3rd exponent bits, which is the + * case for heavyRemPiO2 remainders (their absolute values are >= + * Double.longBitsToDouble(0x3000000000000000L) + * = 1.727233711018889E-77, and even if they were not, turning these + * bits from 0 to 1 on decoding would not change the absolute error + * much), and also works for +-Infinity or NaN encoding. + * @param quadrant Must be in [0,3]. + * @return Bits holding remainder, and quadrant instead of + * reamainder's 2nd and 3rd exponent bits. + */ + static long encodeRemainderAndQuadrant(double remainder, int quadrant) { + final long bits = Double.doubleToRawLongBits(remainder); + return (bits&QUADRANT_BITS_0_MASK)|(((long)quadrant)<<60); + } + + static double decodeRemainder(long bits) { + return Double.longBitsToDouble((bits&QUADRANT_BITS_0_MASK)|QUADRANT_PLACE_BITS); + } + + static int decodeQuadrant(long bits) { + return ((int)(bits>>60))&3; + } + + /* + * JDK-based remainders. + * Since a strict one for (% (PI/2)) is needed for heavyRemainderPiO2, + * we need it in this class. + * Then, for homogeneity, we put them all in this class. + * Then, to avoid code duplication for these slow-anyway methods, + * we just stick with strict versions, for both FastMath and StrictFastMath. + */ + + /** + * @param angle Angle, in radians. + * @return Remainder of (angle % (2*PI)), in [-PI,PI]. + */ + static strictfp double jdkRemainderTwoPi(double angle) { + final double sin = StrictMath.sin(angle); + final double cos = StrictMath.cos(angle); + return StrictMath.atan2(sin, cos); + } + + /** + * @param angle Angle, in radians. + * @return Remainder of (angle % PI), in [-PI/2,PI/2]. + */ + static strictfp double jdkRemainderPi(double angle) { + final double sin = StrictMath.sin(angle); + final double cos = StrictMath.cos(angle); + /* + * Making sure atan2's result ends up in [-PI/2,PI/2], + * i.e. has maximum accuracy. + */ + return StrictMath.atan2(sin, Math.abs(cos)); + } + + /** + * @param angle Angle, in radians. + * @return Bits of double corresponding to remainder of (angle % (PI/2)), + * in [-PI/4,PI/4], with quadrant encoded in exponent bits. + */ + static strictfp long jdkRemainderPiO2(double angle, boolean negateRem) { + final double sin = StrictMath.sin(angle); + final double cos = StrictMath.cos(angle); + + /* + * Computing quadrant first, and then computing + * atan2, to make sure its result ends up in [-PI/4,PI/4], + * i.e. has maximum accuracy. + */ + + final int q; + final double sinForAtan2; + final double cosForAtan2; + if (cos >= (SQRT_2/2)) { + // [-PI/4,PI/4] + q = 0; + sinForAtan2 = sin; + cosForAtan2 = cos; + } else if (cos <= -(SQRT_2/2)) { + // [3*PI/4,5*PI/4] + q = 2; + sinForAtan2 = -sin; + cosForAtan2 = -cos; + } else if (sin > 0.0) { + // [PI/4,3*PI/4] + q = 1; + sinForAtan2 = -cos; + cosForAtan2 = sin; + } else { + // [5*PI/4,7*PI/4] + q = 3; + sinForAtan2 = cos; + cosForAtan2 = -sin; + } + + double fw = StrictMath.atan2(sinForAtan2, cosForAtan2); + + return encodeRemainderAndQuadrant(negateRem ? -fw : fw, q); + } + + /* + * Our remainders implementations. + */ + + /** + * @param angle Angle, in radians. Must not be NaN nor +-Infinity. + * @return Remainder of (angle % (2*PI)), in [-PI,PI]. + */ + static strictfp double heavyRemainderTwoPi(double angle) { + final long remAndQuad = heavyRemainderPiO2(angle, false); + final double rem = decodeRemainder(remAndQuad); + final int q = decodeQuadrant(remAndQuad); + if (q == 0) { + return rem; + } else if (q == 1) { + return (rem + PIO2_LO) + PIO2_HI; + } else if (q == 2) { + if (rem < 0.0) { + return (rem + PI_LO) + PI_HI; + } else { + return (rem - PI_LO) - PI_HI; + } + } else { + return (rem - PIO2_LO) - PIO2_HI; + } + } + + /** + * @param angle Angle, in radians. Must not be NaN nor +-Infinity. + * @return Remainder of (angle % PI), in [-PI/2,PI/2]. + */ + static strictfp double heavyRemainderPi(double angle) { + final long remAndQuad = heavyRemainderPiO2(angle, false); + final double rem = decodeRemainder(remAndQuad); + final int q = decodeQuadrant(remAndQuad); + if ((q&1) != 0) { + // q is 1 or 3 + if (rem < 0.0) { + return (rem + PIO2_LO) + PIO2_HI; + } else { + return (rem - PIO2_LO) - PIO2_HI; + } + } + return rem; + } + + /** + * Remainder using an accurate definition of PI. + * Derived from a fdlibm treatment called __kernel_rem_pio2. + * + * Not defining a non-strictfp version for FastMath, to avoid duplicating + * its long and messy code, and because it's slow anyway, and should be + * rarely used when speed matters. + * + * @param angle Angle, in radians. Must not be NaN nor +-Infinity. + * @param negateRem True if remainder must be negated before encoded into returned long. + * @return Bits of double corresponding to remainder of (angle % (PI/2)), + * in [-PI/4,PI/4], with quadrant encoded in exponent bits. + */ + static strictfp long heavyRemainderPiO2(double angle, boolean negateRem) { + + /* + * fdlibm treatments unrolled, to avoid garbage and be OOME-free, + * corresponding to: + * 1) initial jk = 4 (precision = 3 = 64 bits (extended)), + * which is more accurate than using precision = 2 + * (53 bits, double), even though we work with doubles + * and use strictfp! + * 2) max lengths of 8 for f[], 6 for q[], fq[] and iq[]. + * 3) at most one recomputation (one goto). + * These limitations were experimentally found to + * be sufficient for billions of random doubles + * of random magnitudes. + * For the rare cases that our unrolled treatments can't handle, + * we fall back to a JDK-based implementation. + */ + + int n,i,j,ih; + double fw; + + /* + * Turning angle into 24-bits integer chunks. + * Done outside __kernel_rem_pio2, but we factor it inside our method. + */ + + // Reworking exponent to have a value < 2^24. + final long lx = Double.doubleToRawLongBits(angle); + final long exp = ((lx>>52)&0x7FF) - (1023+23); + double z = Double.longBitsToDouble(lx - (exp<<52)); + + double x0 = (double)(int)z; + z = (z-x0)*TWO_POW_24; + double x1 = (double)(int)z; + z = (z-x1)*TWO_POW_24; + double x2 = (double)(int)z; + + final int e0 = (int)exp; + // in [1,3] + final int nx = (x2 == 0.0) ? ((x1 == 0.0) ? 1 : 2) : 3; + + /* + * + */ + + double f0,f1,f2,f3,f4,f5,f6,f7; + double q0,q1,q2,q3,q4,q5; + int iq0,iq1,iq2,iq3,iq4,iq5; + + int jk = 4; + + int jx = nx-1; + int jv = Math.max(0,(e0-3)/24); + // In fdlibm, this is q0, but we prefer to use q0 for q[0]. + int qZero = e0-24*(jv+1); + + j = jv-jx; + if (jx == 0) { + f6 = 0.0; + f5 = 0.0; + f4 = (j >= -4) ? TWO_OVER_PI_TAB[j+4] : 0.0; + f3 = (j >= -3) ? TWO_OVER_PI_TAB[j+3] : 0.0; + f2 = (j >= -2) ? TWO_OVER_PI_TAB[j+2] : 0.0; + f1 = (j >= -1) ? TWO_OVER_PI_TAB[j+1] : 0.0; + f0 = (j >= 0) ? TWO_OVER_PI_TAB[j] : 0.0; + + q0 = x0*f0; + q1 = x0*f1; + q2 = x0*f2; + q3 = x0*f3; + q4 = x0*f4; + } else if (jx == 1) { + f6 = 0.0; + f5 = (j >= -5) ? TWO_OVER_PI_TAB[j+5] : 0.0; + f4 = (j >= -4) ? TWO_OVER_PI_TAB[j+4] : 0.0; + f3 = (j >= -3) ? TWO_OVER_PI_TAB[j+3] : 0.0; + f2 = (j >= -2) ? TWO_OVER_PI_TAB[j+2] : 0.0; + f1 = (j >= -1) ? TWO_OVER_PI_TAB[j+1] : 0.0; + f0 = (j >= 0) ? TWO_OVER_PI_TAB[j] : 0.0; + + q0 = x0*f1 + x1*f0; + q1 = x0*f2 + x1*f1; + q2 = x0*f3 + x1*f2; + q3 = x0*f4 + x1*f3; + q4 = x0*f5 + x1*f4; + } else { // jx == 2 + f6 = (j >= -6) ? TWO_OVER_PI_TAB[j+6] : 0.0; + f5 = (j >= -5) ? TWO_OVER_PI_TAB[j+5] : 0.0; + f4 = (j >= -4) ? TWO_OVER_PI_TAB[j+4] : 0.0; + f3 = (j >= -3) ? TWO_OVER_PI_TAB[j+3] : 0.0; + f2 = (j >= -2) ? TWO_OVER_PI_TAB[j+2] : 0.0; + f1 = (j >= -1) ? TWO_OVER_PI_TAB[j+1] : 0.0; + f0 = (j >= 0) ? TWO_OVER_PI_TAB[j] : 0.0; + + q0 = x0*f2 + x1*f1 + x2*f0; + q1 = x0*f3 + x1*f2 + x2*f1; + q2 = x0*f4 + x1*f3 + x2*f2; + q3 = x0*f5 + x1*f4 + x2*f3; + q4 = x0*f6 + x1*f5 + x2*f4; + } + + double twoPowQZero = twoPowNormal(qZero); + + int jz = jk; + + /* + * Unrolling of first round. + */ + + z = q4; + fw = (double)(int)(TWO_POW_N24*z); + iq0 = (int)(z-TWO_POW_24*fw); + z = q3+fw; + fw = (double)(int)(TWO_POW_N24*z); + iq1 = (int)(z-TWO_POW_24*fw); + z = q2+fw; + fw = (double)(int)(TWO_POW_N24*z); + iq2 = (int)(z-TWO_POW_24*fw); + z = q1+fw; + fw = (double)(int)(TWO_POW_N24*z); + iq3 = (int)(z-TWO_POW_24*fw); + z = q0+fw; + iq4 = 0; + iq5 = 0; + + z = (z*twoPowQZero) % 8.0; + n = (int)z; + z -= (double)n; + + ih = 0; + if (qZero > 0) { + // Parentheses against code formatter bug. + i = (iq3>>(24-qZero)); + n += i; + iq3 -= i<<(24-qZero); + ih = iq3>>(23-qZero); + } else if (qZero == 0) { + ih = iq3>>23; + } else if (z >= 0.5) { + ih = 2; + } + + if (ih > 0) { + n += 1; + // carry = 1 is common case, + // so using it as initial value. + int carry = 1; + if (iq0 != 0) { + iq0 = 0x1000000 - iq0; + iq1 = 0xFFFFFF - iq1; + iq2 = 0xFFFFFF - iq2; + iq3 = 0xFFFFFF - iq3; + } else if (iq1 != 0) { + iq1 = 0x1000000 - iq1; + iq2 = 0xFFFFFF - iq2; + iq3 = 0xFFFFFF - iq3; + } else if (iq2 != 0) { + iq2 = 0x1000000 - iq2; + iq3 = 0xFFFFFF - iq3; + } else if (iq3 != 0) { + iq3 = 0x1000000 - iq3; + } else { + carry = 0; + } + if (qZero > 0) { + if (qZero == 1) { + iq3 &= 0x7FFFFF; + } else if (qZero == 2) { + iq3 &= 0x3FFFFF; + } + } + if (ih == 2) { + z = 1.0 - z; + if (carry != 0) { + z -= twoPowQZero; + } + } + } + + if (z == 0.0) { + if (iq3 == 0) { + // With random values of random magnitude, + // probability for this to happen seems lower than 1e-6. + // jz would be more than just incremented by one, + // which our unrolling doesn't support. + return jdkRemainderPiO2(angle, negateRem); + } + if (jx == 0) { + f5 = TWO_OVER_PI_TAB[jv+5]; + q5 = x0*f5; + } else if (jx == 1) { + f6 = TWO_OVER_PI_TAB[jv+5]; + q5 = x0*f6 + x1*f5; + } else { // jx == 2 + f7 = TWO_OVER_PI_TAB[jv+5]; + q5 = x0*f7 + x1*f6 + x2*f5; + } + + jz++; + + /* + * Unrolling of second round. + */ + + z = q5; + fw = (double)(int)(TWO_POW_N24*z); + iq0 = (int)(z-TWO_POW_24*fw); + z = q4+fw; + fw = (double)(int)(TWO_POW_N24*z); + iq1 = (int)(z-TWO_POW_24*fw); + z = q3+fw; + fw = (double)(int)(TWO_POW_N24*z); + iq2 = (int)(z-TWO_POW_24*fw); + z = q2+fw; + fw = (double)(int)(TWO_POW_N24*z); + iq3 = (int)(z-TWO_POW_24*fw); + z = q1+fw; + fw = (double)(int)(TWO_POW_N24*z); + iq4 = (int)(z-TWO_POW_24*fw); + z = q0+fw; + iq5 = 0; + + z = (z*twoPowQZero) % 8.0; + n = (int)z; + z -= (double)n; + + ih = 0; + if (qZero > 0) { + // Parentheses against code formatter bug. + i = (iq4>>(24-qZero)); + n += i; + iq4 -= i<<(24-qZero); + ih = iq4>>(23-qZero); + } else if (qZero == 0) { + ih = iq4>>23; + } else if (z >= 0.5) { + ih = 2; + } + + if (ih > 0) { + n += 1; + // carry = 1 is common case, + // so using it as initial value. + int carry = 1; + if (iq0 != 0) { + iq0 = 0x1000000 - iq0; + iq1 = 0xFFFFFF - iq1; + iq2 = 0xFFFFFF - iq2; + iq3 = 0xFFFFFF - iq3; + iq4 = 0xFFFFFF - iq4; + } else if (iq1 != 0) { + iq1 = 0x1000000 - iq1; + iq2 = 0xFFFFFF - iq2; + iq3 = 0xFFFFFF - iq3; + iq4 = 0xFFFFFF - iq4; + } else if (iq2 != 0) { + iq2 = 0x1000000 - iq2; + iq3 = 0xFFFFFF - iq3; + iq4 = 0xFFFFFF - iq4; + } else if (iq3 != 0) { + iq3 = 0x1000000 - iq3; + iq4 = 0xFFFFFF - iq4; + } else if (iq4 != 0) { + iq4 = 0x1000000 - iq4; + } else { + carry = 0; + } + if (qZero > 0) { + if (qZero == 1) { + iq4 &= 0x7FFFFF; + } else if (qZero == 2) { + iq4 &= 0x3FFFFF; + } + } + if (ih == 2) { + z = 1.0 - z; + if (carry != 0) { + z -= twoPowQZero; + } + } + } + + if (z == 0.0) { + if (iq4 == 0) { + // Case not encountered in tests, but still handling it. + // Would require a third loop unrolling. + return jdkRemainderPiO2(angle, negateRem); + } else { + // z == 0.0, and iq4 != 0, + // so we remove 24 from qZero only once, + // but since we no longer use qZero, + // we just bother to multiply its 2-power + // by 2^-24. + jz--; + twoPowQZero *= TWO_POW_N24; + } + } else { + // z != 0.0 at end of second round. + } + } else { + // z != 0.0 at end of first round. + } + + /* + * After loop. + */ + + if (z != 0.0) { + z /= twoPowQZero; + if (z >= TWO_POW_24) { + fw = (double)(int)(TWO_POW_N24*z); + if (jz == jk) { + iq4 = (int)(z-TWO_POW_24*fw); + jz++; // jz to 5 + // Not using qZero anymore so not updating it. + twoPowQZero *= TWO_POW_24; + iq5 = (int)fw; + } else { // jz == jk+1 == 5 + // Case not encountered in tests, but still handling it. + // Would require use of iq6, with jz = 6. + return jdkRemainderPiO2(angle, negateRem); + } + } else { + if (jz == jk) { + iq4 = (int)z; + } else { // jz == jk+1 == 5 + // Case not encountered in tests, but still handling it. + iq5 = (int)z; + } + } + } + + fw = twoPowQZero; + + if (jz == 5) { + q5 = fw*(double)iq5; + fw *= TWO_POW_N24; + } else { + q5 = 0.0; + } + q4 = fw*(double)iq4; + fw *= TWO_POW_N24; + q3 = fw*(double)iq3; + fw *= TWO_POW_N24; + q2 = fw*(double)iq2; + fw *= TWO_POW_N24; + q1 = fw*(double)iq1; + fw *= TWO_POW_N24; + q0 = fw*(double)iq0; + + /* + * We just use HI part of the result. + */ + + fw = PIO2_TAB0*q5; + fw += PIO2_TAB0*q4 + PIO2_TAB1*q5; + fw += PIO2_TAB0*q3 + PIO2_TAB1*q4 + PIO2_TAB2*q5; + fw += PIO2_TAB0*q2 + PIO2_TAB1*q3 + PIO2_TAB2*q4 + PIO2_TAB3*q5; + fw += PIO2_TAB0*q1 + PIO2_TAB1*q2 + PIO2_TAB2*q3 + PIO2_TAB3*q4 + PIO2_TAB4*q5; + fw += PIO2_TAB0*q0 + PIO2_TAB1*q1 + PIO2_TAB2*q2 + PIO2_TAB3*q3 + PIO2_TAB4*q4 + PIO2_TAB5*q5; + + if ((ih != 0) ^ negateRem) { + fw = -fw; + } + + return encodeRemainderAndQuadrant(fw, n&3); + } + + //-------------------------------------------------------------------------- + // PRIVATE METHODS + //-------------------------------------------------------------------------- + + /** + * Redefined here, to avoid cyclic dependency with (Strict)FastMath. + * + * @param value A double value. + * @return -1 if sign bit is 1, 1 if sign bit is 0. + */ + private static long signFromBit_antiCyclic(double value) { + // Returning a long, to avoid useless cast into int. + return ((Double.doubleToRawLongBits(value)>>62)|1); + } + + private static boolean getBooleanProperty( + final String key, + boolean defaultValue) { + final String tmp = System.getProperty(key); + if (tmp != null) { + return Boolean.parseBoolean(tmp); + } else { + return defaultValue; + } + } + + /** + * Use look-up tables size power through this method, + * to make sure is it small in case java.lang.Math + * is directly used. + */ + private static int getTabSizePower(int tabSizePower) { + return (FM_USE_JDK_MATH && SFM_USE_JDK_MATH) ? Math.min(2, tabSizePower) : tabSizePower; + } +} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/DoubleWrapper.java b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/DoubleWrapper.java new file mode 100644 index 000000000..e7adc8d59 --- /dev/null +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/DoubleWrapper.java @@ -0,0 +1,13 @@ +/* + * 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.jafama; + +public class DoubleWrapper { + public double value; + @Override + public String toString() { + return Double.toString(this.value); + } +} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/FastMath.java b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/FastMath.java new file mode 100644 index 000000000..a83c01f7b --- /dev/null +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/FastMath.java @@ -0,0 +1,2986 @@ +/* + * 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.jafama; + +/** + * Faster (hopefully) versions of java.lang.Math methods, plus additional ones. + * Cf. README.txt for more info. + */ +public final class FastMath extends CmnFastMath { + + //-------------------------------------------------------------------------- + // CONFIGURATION + //-------------------------------------------------------------------------- + + private static final boolean USE_JDK_MATH = FM_USE_JDK_MATH; + + private static final boolean USE_REDEFINED_LOG = FM_USE_REDEFINED_LOG; + + private static final boolean USE_REDEFINED_SQRT = FM_USE_REDEFINED_SQRT; + + private static final boolean USE_POWTABS_FOR_ASIN = FM_USE_POWTABS_FOR_ASIN; + + //-------------------------------------------------------------------------- + // PUBLIC METHODS + //-------------------------------------------------------------------------- + + /* + * trigonometry + */ + + /** + * @param angle Angle in radians. + * @return Angle sine. + */ + public static double sin(double angle) { + if (USE_JDK_MATH) { + return Math.sin(angle); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + if (angle > SIN_COS_MAX_VALUE_FOR_INT_MODULO) { + if (false) { + // Can give very bad relative error near PI (mod 2*PI). + angle = remainderTwoPi(angle); + if (angle < 0.0) { + angle = -angle; + negateResult = !negateResult; + } + } else { + final long remAndQuad = remainderPiO2(angle); + angle = decodeRemainder(remAndQuad); + final double sin; + final int q = decodeQuadrant(remAndQuad); + if (q == 0) { + sin = sin(angle); + } else if (q == 1) { + sin = cos(angle); + } else if (q == 2) { + sin = -sin(angle); + } else { + sin = -cos(angle); + } + return (negateResult ? -sin : sin); + } + } + // index: possibly outside tables range. + int index = (int)(angle * SIN_COS_INDEXER + 0.5); + double delta = (angle - index * SIN_COS_DELTA_HI) - index * SIN_COS_DELTA_LO; + // Making sure index is within tables range. + // Last value of each table is the same than first, + // so we ignore it (tabs size minus one) for modulo. + index &= (SIN_COS_TABS_SIZE-2); // index % (SIN_COS_TABS_SIZE-1) + double indexSin = MyTSinCos.sinTab[index]; + double indexCos = MyTSinCos.cosTab[index]; + double result = indexSin + delta * (indexCos + delta * (-indexSin * ONE_DIV_F2 + delta * (-indexCos * ONE_DIV_F3 + delta * indexSin * ONE_DIV_F4))); + return negateResult ? -result : result; + } + + /** + * Quick sin, with accuracy of about 1.6e-3 (PI/) + * for |angle| < 6588395.0 (Integer.MAX_VALUE * (2*PI/) - 2) + * (- 2 due to removing PI/2 before using cosine tab), + * and no accuracy at all for larger values. + * + * @param angle Angle in radians. + * @return Angle sine. + */ + public static double sinQuick(double angle) { + if (USE_JDK_MATH) { + return Math.sin(angle); + } + return MyTSinCos.cosTab[((int)(Math.abs(angle-Math.PI/2) * SIN_COS_INDEXER + 0.5)) & (SIN_COS_TABS_SIZE-2)]; + } + + /** + * @param angle Angle in radians. + * @return Angle cosine. + */ + public static double cos(double angle) { + if (USE_JDK_MATH) { + return Math.cos(angle); + } + angle = Math.abs(angle); + if (angle > SIN_COS_MAX_VALUE_FOR_INT_MODULO) { + if (false) { + // Can give very bad relative error near PI (mod 2*PI). + angle = remainderTwoPi(angle); + if (angle < 0.0) { + angle = -angle; + } + } else { + final long remAndQuad = remainderPiO2(angle); + angle = decodeRemainder(remAndQuad); + final double cos; + final int q = decodeQuadrant(remAndQuad); + if (q == 0) { + cos = cos(angle); + } else if (q == 1) { + cos = -sin(angle); + } else if (q == 2) { + cos = -cos(angle); + } else { + cos = sin(angle); + } + return cos; + } + } + // index: possibly outside tables range. + int index = (int)(angle * SIN_COS_INDEXER + 0.5); + double delta = (angle - index * SIN_COS_DELTA_HI) - index * SIN_COS_DELTA_LO; + // Making sure index is within tables range. + // Last value of each table is the same than first, + // so we ignore it (tabs size minus one) for modulo. + index &= (SIN_COS_TABS_SIZE-2); // index % (SIN_COS_TABS_SIZE-1) + double indexCos = MyTSinCos.cosTab[index]; + double indexSin = MyTSinCos.sinTab[index]; + return indexCos + delta * (-indexSin + delta * (-indexCos * ONE_DIV_F2 + delta * (indexSin * ONE_DIV_F3 + delta * indexCos * ONE_DIV_F4))); + } + + /** + * Quick cos, with accuracy of about 1.6e-3 (PI/) + * for |angle| < 6588397.0 (Integer.MAX_VALUE * (2*PI/)), + * and no accuracy at all for larger values. + * + * @param angle Angle in radians. + * @return Angle cosine. + */ + public static double cosQuick(double angle) { + if (USE_JDK_MATH) { + return Math.cos(angle); + } + return MyTSinCos.cosTab[((int)(Math.abs(angle) * SIN_COS_INDEXER + 0.5)) & (SIN_COS_TABS_SIZE-2)]; + } + + /** + * Computes sine and cosine together. + * + * @param angle Angle in radians. + * @param cosine (out) Angle cosine. + * @return Angle sine. + */ + public static double sinAndCos(double angle, DoubleWrapper cosine) { + if (USE_JDK_MATH) { + cosine.value = Math.cos(angle); + return Math.sin(angle); + } + // Using the same algorithm than sin(double) method, + // and computing also cosine at the end. + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + if (angle > SIN_COS_MAX_VALUE_FOR_INT_MODULO) { + if (false) { + // Can give very bad relative error near PI (mod 2*PI). + angle = remainderTwoPi(angle); + if (angle < 0.0) { + angle = -angle; + negateResult = !negateResult; + } + } else { + final long remAndQuad = remainderPiO2(angle); + angle = decodeRemainder(remAndQuad); + final double sin; + final int q = decodeQuadrant(remAndQuad); + if (q == 0) { + sin = sin(angle); + cosine.value = cos(angle); + } else if (q == 1) { + sin = cos(angle); + cosine.value = -sin(angle); + } else if (q == 2) { + sin = -sin(angle); + cosine.value = -cos(angle); + } else { + sin = -cos(angle); + cosine.value = sin(angle); + } + return (negateResult ? -sin : sin); + } + } + int index = (int)(angle * SIN_COS_INDEXER + 0.5); + double delta = (angle - index * SIN_COS_DELTA_HI) - index * SIN_COS_DELTA_LO; + index &= (SIN_COS_TABS_SIZE-2); // index % (SIN_COS_TABS_SIZE-1) + double indexSin = MyTSinCos.sinTab[index]; + double indexCos = MyTSinCos.cosTab[index]; + // Could factor some multiplications (delta * factorials), but then is less accurate. + cosine.value = indexCos + delta * (-indexSin + delta * (-indexCos * ONE_DIV_F2 + delta * (indexSin * ONE_DIV_F3 + delta * indexCos * ONE_DIV_F4))); + double result = indexSin + delta * (indexCos + delta * (-indexSin * ONE_DIV_F2 + delta * (-indexCos * ONE_DIV_F3 + delta * indexSin * ONE_DIV_F4))); + return negateResult ? -result : result; + } + + /** + * Can have very bad relative error near +-PI/2, + * but of the same magnitude than the relative delta between + * StrictMath.tan(PI/2) and StrictMath.tan(nextDown(PI/2)). + * + * @param angle Angle in radians. + * @return Angle tangent. + */ + public static double tan(double angle) { + if (USE_JDK_MATH) { + return Math.tan(angle); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + if (angle > TAN_MAX_VALUE_FOR_INT_MODULO) { + angle = remainderPi(angle); + if (angle < 0.0) { + angle = -angle; + negateResult = !negateResult; + } + } + // index: possibly outside tables range. + int index = (int)(angle * TAN_INDEXER + 0.5); + double delta = (angle - index * TAN_DELTA_HI) - index * TAN_DELTA_LO; + // Making sure index is within tables range. + // index modulo PI, i.e. 2*(virtual tab size minus one). + index &= (2*(TAN_VIRTUAL_TABS_SIZE-1)-1); // index % (2*(TAN_VIRTUAL_TABS_SIZE-1)) + // Here, index is in [0,2*(TAN_VIRTUAL_TABS_SIZE-1)-1], i.e. indicates an angle in [0,PI[. + if (index > (TAN_VIRTUAL_TABS_SIZE-1)) { + index = (2*(TAN_VIRTUAL_TABS_SIZE-1)) - index; + delta = -delta; + negateResult = !negateResult; + } + double result; + if (index < TAN_TABS_SIZE) { + result = MyTTan.tanTab[index] + + delta * (MyTTan.tanDer1DivF1Tab[index] + + delta * (MyTTan.tanDer2DivF2Tab[index] + + delta * (MyTTan.tanDer3DivF3Tab[index] + + delta * MyTTan.tanDer4DivF4Tab[index]))); + } else { // angle in ]TAN_MAX_VALUE_FOR_TABS,TAN_MAX_VALUE_FOR_INT_MODULO], or angle is NaN + // Using tan(angle) == 1/tan(PI/2-angle) formula: changing angle (index and delta), and inverting. + index = (TAN_VIRTUAL_TABS_SIZE-1) - index; + result = 1/(MyTTan.tanTab[index] + - delta * (MyTTan.tanDer1DivF1Tab[index] + - delta * (MyTTan.tanDer2DivF2Tab[index] + - delta * (MyTTan.tanDer3DivF3Tab[index] + - delta * MyTTan.tanDer4DivF4Tab[index])))); + } + return negateResult ? -result : result; + } + + /** + * @param value Value in [-1,1]. + * @return Value arcsine, in radians, in [-PI/2,PI/2]. + */ + public static double asin(double value) { + if (USE_JDK_MATH) { + return Math.asin(value); + } + boolean negateResult = false; + if (value < 0.0) { + value = -value; + negateResult = true; + } + if (value <= ASIN_MAX_VALUE_FOR_TABS) { + int index = (int)(value * ASIN_INDEXER + 0.5); + double delta = value - index * ASIN_DELTA; + double result = MyTAsin.asinTab[index] + + delta * (MyTAsin.asinDer1DivF1Tab[index] + + delta * (MyTAsin.asinDer2DivF2Tab[index] + + delta * (MyTAsin.asinDer3DivF3Tab[index] + + delta * MyTAsin.asinDer4DivF4Tab[index]))); + return negateResult ? -result : result; + } else if (USE_POWTABS_FOR_ASIN && (value <= ASIN_MAX_VALUE_FOR_POWTABS)) { + int index = (int)(powFast(value * ASIN_POWTABS_ONE_DIV_MAX_VALUE, ASIN_POWTABS_POWER) * ASIN_POWTABS_SIZE_MINUS_ONE + 0.5); + double delta = value - MyTAsinPow.asinParamPowTab[index]; + double result = MyTAsinPow.asinPowTab[index] + + delta * (MyTAsinPow.asinDer1DivF1PowTab[index] + + delta * (MyTAsinPow.asinDer2DivF2PowTab[index] + + delta * (MyTAsinPow.asinDer3DivF3PowTab[index] + + delta * MyTAsinPow.asinDer4DivF4PowTab[index]))); + return negateResult ? -result : result; + } else { // value > ASIN_MAX_VALUE_FOR_TABS, or value is NaN + // This part is derived from fdlibm. + if (value < 1.0) { + double t = (1.0 - value)*0.5; + double p = t*(ASIN_PS0+t*(ASIN_PS1+t*(ASIN_PS2+t*(ASIN_PS3+t*(ASIN_PS4+t*ASIN_PS5))))); + double q = 1.0+t*(ASIN_QS1+t*(ASIN_QS2+t*(ASIN_QS3+t*ASIN_QS4))); + double s = sqrt(t); + double z = s+s*(p/q); + double result = ASIN_PIO2_HI-((z+z)-ASIN_PIO2_LO); + return negateResult ? -result : result; + } else { // value >= 1.0, or value is NaN + if (value == 1.0) { + return negateResult ? -Math.PI/2 : Math.PI/2; + } else { + return Double.NaN; + } + } + } + } + + /** + * If value is not NaN and is outside [-1,1] range, closest value in this range is used. + * + * @param value Value in [-1,1]. + * @return Value arcsine, in radians, in [-PI/2,PI/2]. + */ + public static double asinInRange(double value) { + if (value <= -1.0) { + return -Math.PI/2; + } else if (value >= 1.0) { + return Math.PI/2; + } else { + return asin(value); + } + } + + /** + * @param value Value in [-1,1]. + * @return Value arccosine, in radians, in [0,PI]. + */ + public static double acos(double value) { + if (USE_JDK_MATH) { + return Math.acos(value); + } + return Math.PI/2 - asin(value); + } + + /** + * If value is not NaN and is outside [-1,1] range, + * closest value in this range is used. + * + * @param value Value in [-1,1]. + * @return Value arccosine, in radians, in [0,PI]. + */ + public static double acosInRange(double value) { + if (value <= -1.0) { + return Math.PI; + } else if (value >= 1.0) { + return 0.0; + } else { + return acos(value); + } + } + + /** + * @param value A double value. + * @return Value arctangent, in radians, in [-PI/2,PI/2]. + */ + public static double atan(double value) { + if (USE_JDK_MATH) { + return Math.atan(value); + } + boolean negateResult = false; + if (value < 0.0) { + value = -value; + negateResult = true; + } + if (value == 1.0) { + // We want "exact" result for 1.0. + return negateResult ? -Math.PI/4 : Math.PI/4; + } else if (value <= ATAN_MAX_VALUE_FOR_TABS) { + int index = (int)(value * ATAN_INDEXER + 0.5); + double delta = value - index * ATAN_DELTA; + double result = MyTAtan.atanTab[index] + + delta * (MyTAtan.atanDer1DivF1Tab[index] + + delta * (MyTAtan.atanDer2DivF2Tab[index] + + delta * (MyTAtan.atanDer3DivF3Tab[index] + + delta * MyTAtan.atanDer4DivF4Tab[index]))); + return negateResult ? -result : result; + } else { // value > ATAN_MAX_VALUE_FOR_TABS, or value is NaN + // This part is derived from fdlibm. + if (value < TWO_POW_66) { + double x = -1/value; + double x2 = x*x; + double x4 = x2*x2; + double s1 = x2*(ATAN_AT0+x4*(ATAN_AT2+x4*(ATAN_AT4+x4*(ATAN_AT6+x4*(ATAN_AT8+x4*ATAN_AT10))))); + double s2 = x4*(ATAN_AT1+x4*(ATAN_AT3+x4*(ATAN_AT5+x4*(ATAN_AT7+x4*ATAN_AT9)))); + double result = ATAN_HI3-((x*(s1+s2)-ATAN_LO3)-x); + return negateResult ? -result : result; + } else { // value >= 2^66, or value is NaN + if (value != value) { + return Double.NaN; + } else { + return negateResult ? -Math.PI/2 : Math.PI/2; + } + } + } + } + + /** + * For special values for which multiple conventions could be adopted, + * behaves like Math.atan2(double,double). + * + * @param y Coordinate on y axis. + * @param x Coordinate on x axis. + * @return Angle from x axis positive side to (x,y) position, in radians, in [-PI,PI]. + * Angle measure is positive when going from x axis to y axis (positive sides). + */ + public static double atan2(double y, double x) { + if (USE_JDK_MATH) { + return Math.atan2(y,x); + } + /* + * Using sub-methods, to make method lighter for general case, + * and to avoid JIT-optimization crash on NaN. + */ + if (x > 0.0) { + if (y == 0.0) { + // +-0.0 + return y; + } + if (x == Double.POSITIVE_INFINITY) { + return atan2_pinf_yyy(y); + } else { + return atan(y/x); + } + } else if (x < 0.0) { + if (y == 0.0) { + return signFromBit(y) * Math.PI; + } + if (x == Double.NEGATIVE_INFINITY) { + return atan2_ninf_yyy(y); + } else if (y > 0.0) { + return Math.PI/2 - atan(x/y); + } else if (y < 0.0) { + return -Math.PI/2 - atan(x/y); + } else { + return Double.NaN; + } + } else { + return atan2_yyy_zeroOrNaN(y, x); + } + } + + /** + * Gives same result as Math.toRadians for some particular values + * like 90.0, 180.0 or 360.0, but is faster (no division). + * + * @param angdeg Angle value in degrees. + * @return Angle value in radians. + */ + public static double toRadians(double angdeg) { + if (USE_JDK_MATH) { + return Math.toRadians(angdeg); + } + return angdeg * (Math.PI/180); + } + + /** + * Gives same result as Math.toDegrees for some particular values + * like Math.PI/2, Math.PI or 2*Math.PI, but is faster (no division). + * + * @param angrad Angle value in radians. + * @return Angle value in degrees. + */ + public static double toDegrees(double angrad) { + if (USE_JDK_MATH) { + return Math.toDegrees(angrad); + } + return angrad * (180/Math.PI); + } + + /** + * @param sign Sign of the angle: true for positive, false for negative. + * @param degrees Degrees, in [0,180]. + * @param minutes Minutes, in [0,59]. + * @param seconds Seconds, in [0.0,60.0[. + * @return Angle in radians. + */ + public static double toRadians(boolean sign, int degrees, int minutes, double seconds) { + return toRadians(toDegrees(sign, degrees, minutes, seconds)); + } + + /** + * @param sign Sign of the angle: true for positive, false for negative. + * @param degrees Degrees, in [0,180]. + * @param minutes Minutes, in [0,59]. + * @param seconds Seconds, in [0.0,60.0[. + * @return Angle in degrees. + */ + public static double toDegrees(boolean sign, int degrees, int minutes, double seconds) { + double signFactor = sign ? 1.0 : -1.0; + return signFactor * (degrees + (1.0/60)*(minutes + (1.0/60)*seconds)); + } + + /** + * @param angrad Angle in radians. + * @param degrees (out) Degrees, in [0,180]. + * @param minutes (out) Minutes, in [0,59]. + * @param seconds (out) Seconds, in [0.0,60.0[. + * @return true if the resulting angle in [-180deg,180deg] is positive, false if it is negative. + */ + public static boolean toDMS(double angrad, IntWrapper degrees, IntWrapper minutes, DoubleWrapper seconds) { + // Computing longitude DMS. + double tmp = toDegrees(normalizeMinusPiPi(angrad)); + boolean isNeg = (tmp < 0.0); + if (isNeg) { + tmp = -tmp; + } + degrees.value = (int)tmp; + tmp = (tmp-degrees.value)*60.0; + minutes.value = (int)tmp; + seconds.value = Math.min((tmp-minutes.value)*60.0,DOUBLE_BEFORE_60); + return !isNeg; + } + + /** + * NB: Since 2*Math.PI < 2*PI, a span of 2*Math.PI does not mean full angular range. + * ex.: isInClockwiseDomain(0.0, 2*Math.PI, -1e-20) returns false. + * ---> For full angular range, use a span > 2*Math.PI, like 2*PI_SUP constant of this class. + * + * @param startAngRad An angle, in radians. + * @param angSpanRad An angular span, >= 0.0, in radians. + * @param angRad An angle, in radians. + * @return true if angRad is in the clockwise angular domain going from startAngRad, over angSpanRad, + * extremities included, false otherwise. + */ + public static boolean isInClockwiseDomain(double startAngRad, double angSpanRad, double angRad) { + if (Math.abs(angRad) < -TWO_MATH_PI_IN_MINUS_PI_PI) { + // special case for angular values of small magnitude + if (angSpanRad <= 2*Math.PI) { + if (angSpanRad < 0.0) { + // empty domain + return false; + } + // angSpanRad is in [0,2*PI] + startAngRad = normalizeMinusPiPi(startAngRad); + double endAngRad = normalizeMinusPiPi(startAngRad + angSpanRad); + if (startAngRad <= endAngRad) { + return (angRad >= startAngRad) && (angRad <= endAngRad); + } else { + return (angRad >= startAngRad) || (angRad <= endAngRad); + } + } else { // angSpanRad > 2*Math.PI, or is NaN + return (angSpanRad == angSpanRad); + } + } else { + // general case + return (normalizeZeroTwoPi(angRad - startAngRad) <= angSpanRad); + } + } + + /* + * hyperbolic trigonometry + */ + + /** + * Some properties of sinh(x) = (exp(x)-exp(-x))/2: + * 1) defined on ]-Infinity,+Infinity[ + * 2) result in ]-Infinity,+Infinity[ + * 3) sinh(x) = -sinh(-x) (implies sinh(0) = 0) + * 4) sinh(epsilon) ~= epsilon + * 5) lim(sinh(x),x->+Infinity) = +Infinity + * (y increasing exponentially faster than x) + * 6) reaches +Infinity (double overflow) for x >= 710.475860073944, + * i.e. a bit further than exp(x) + * + * @param value A double value. + * @return Value hyperbolic sine. + */ + public static double sinh(double value) { + if (USE_JDK_MATH) { + return Math.sinh(value); + } + // sinh(x) = (exp(x)-exp(-x))/2 + double h; + if (value < 0.0) { + value = -value; + h = -0.5; + } else { + h = 0.5; + } + if (value < 22.0) { + if (value < TWO_POW_N28) { + return (h < 0.0) ? -value : value; + } else { + // sinh(x) + // = (exp(x)-exp(-x))/2 + // = (exp(x)-1/exp(x))/2 + // = (expm1(x) + 1 - 1/(expm1(x)+1))/2 + // = (expm1(x) + (expm1(x)+1)/(expm1(x)+1) - 1/(expm1(x)+1))/2 + // = (expm1(x) + expm1(x)/(expm1(x)+1))/2 + double t = expm1(value); + // Might be more accurate, if value < 1: return h*((t+t)-t*t/(t+1.0)). + return h * (t + t/(t+1.0)); + } + } else if (value < LOG_DOUBLE_MAX_VALUE) { + return h * exp(value); + } else { + double t = exp(value*0.5); + return (h*t)*t; + } + } + + /** + * Some properties of cosh(x) = (exp(x)+exp(-x))/2: + * 1) defined on ]-Infinity,+Infinity[ + * 2) result in [1,+Infinity[ + * 3) cosh(0) = 1 + * 4) cosh(x) = cosh(-x) + * 5) lim(cosh(x),x->+Infinity) = +Infinity + * (y increasing exponentially faster than x) + * 6) reaches +Infinity (double overflow) for x >= 710.475860073944, + * i.e. a bit further than exp(x) + * + * @param value A double value. + * @return Value hyperbolic cosine. + */ + public static double cosh(double value) { + if (USE_JDK_MATH) { + return Math.cosh(value); + } + // cosh(x) = (exp(x)+exp(-x))/2 + if (value < 0.0) { + value = -value; + } + if (value < LOG_TWO_POW_27) { + if (value < TWO_POW_N27) { + // cosh(x) + // = (exp(x)+exp(-x))/2 + // = ((1+x+x^2/2!+...) + (1-x+x^2/2!-...))/2 + // = 1+x^2/2!+x^4/4!+... + // For value of x small in magnitude, the sum of the terms does not add to 1. + return 1; + } else { + // cosh(x) + // = (exp(x)+exp(-x))/2 + // = (exp(x)+1/exp(x))/2 + double t = exp(value); + return 0.5 * (t+1/t); + } + } else if (value < LOG_DOUBLE_MAX_VALUE) { + return 0.5 * exp(value); + } else { + double t = exp(value*0.5); + return (0.5*t)*t; + } + } + + /** + * Much more accurate than cosh(value)-1, + * for arguments (and results) close to zero. + * + * coshm1(-0.0) = -0.0, for homogeneity with + * acosh1p(-0.0) = -0.0. + * + * @param value A double value. + * @return Value hyperbolic cosine, minus 1. + */ + public static double coshm1(double value) { + // cosh(x)-1 = (exp(x)+exp(-x))/2 - 1 + if (value < 0.0) { + value = -value; + } + if (value < LOG_TWO_POW_27) { + if (value < TWO_POW_N27) { + if (value == 0.0) { + // +-0.0 + return value; + } + // Using (expm1(x)+expm1(-x))/2 + // is not accurate for tiny values, + // for expm1 results are of higher + // magnitude than the result and + // of different signs, such as their + // sum is not accurate. + // cosh(x) - 1 + // = (exp(x)+exp(-x))/2 - 1 + // = ((1+x+x^2/2!+...) + (1-x+x^2/2!-...))/2 - 1 + // = x^2/2!+x^4/4!+... + // ~= x^2 * (1/2 + x^2 * 1/24) + // = x^2 * 0.5 (since x < 2^-27) + return 0.5 * value*value; + } else { + // cosh(x) - 1 + // = (exp(x)+exp(-x))/2 - 1 + // = (exp(x)-1+exp(-x)-1)/2 + // = (expm1(x)+expm1(-x))/2 + return 0.5 * (expm1(value)+expm1(-value)); + } + } else if (value < LOG_DOUBLE_MAX_VALUE) { + return 0.5 * exp(value) - 1.0; + } else { + // No need to subtract 1 from result. + double t = exp(value*0.5); + return (0.5*t)*t; + } + } + + /** + * Computes hyperbolic sine and hyperbolic cosine together. + * + * @param value A double value. + * @param hcosine (out) Value hyperbolic cosine. + * @return Value hyperbolic sine. + */ + public static double sinhAndCosh(double value, DoubleWrapper hcosine) { + if (USE_JDK_MATH) { + hcosine.value = Math.cosh(value); + return Math.sinh(value); + } + // Mixup of sinh and cosh treatments: if you modify them, + // you might want to also modify this. + double h; + if (value < 0.0) { + value = -value; + h = -0.5; + } else { + h = 0.5; + } + final double hsine; + // LOG_TWO_POW_27 = 18.714973875118524 + if (value < LOG_TWO_POW_27) { // test from cosh + // sinh + if (value < TWO_POW_N28) { + hsine = (h < 0.0) ? -value : value; + } else { + double t = expm1(value); + hsine = h * (t + t/(t+1.0)); + } + // cosh + if (value < TWO_POW_N27) { + hcosine.value = 1; + } else { + double t = exp(value); + hcosine.value = 0.5 * (t+1/t); + } + } else if (value < 22.0) { // test from sinh + // Here, value is in [18.714973875118524,22.0[. + double t = expm1(value); + hsine = h * (t + t/(t+1.0)); + hcosine.value = 0.5 * (t+1.0); + } else { + if (value < LOG_DOUBLE_MAX_VALUE) { + hsine = h * exp(value); + } else { + double t = exp(value*0.5); + hsine = (h*t)*t; + } + hcosine.value = Math.abs(hsine); + } + return hsine; + } + + /** + * Some properties of tanh(x) = sinh(x)/cosh(x) = (exp(2*x)-1)/(exp(2*x)+1): + * 1) defined on ]-Infinity,+Infinity[ + * 2) result in ]-1,1[ + * 3) tanh(x) = -tanh(-x) (implies tanh(0) = 0) + * 4) tanh(epsilon) ~= epsilon + * 5) lim(tanh(x),x->+Infinity) = 1 + * 6) reaches 1 (double loss of precision) for x = 19.061547465398498 + * + * @param value A double value. + * @return Value hyperbolic tangent. + */ + public static double tanh(double value) { + if (USE_JDK_MATH) { + return Math.tanh(value); + } + // tanh(x) = sinh(x)/cosh(x) + // = (exp(x)-exp(-x))/(exp(x)+exp(-x)) + // = (exp(2*x)-1)/(exp(2*x)+1) + boolean negateResult = false; + if (value < 0.0) { + value = -value; + negateResult = true; + } + double z; + if (value < TANH_1_THRESHOLD) { + if (value < TWO_POW_N55) { + return negateResult ? -value*(1.0-value) : value*(1.0+value); + } else if (value >= 1) { + z = 1.0-2.0/(expm1(value+value)+2.0); + } else { + double t = expm1(-(value+value)); + z = -t/(t+2.0); + } + } else { + z = (value != value) ? Double.NaN : 1.0; + } + return negateResult ? -z : z; + } + + /** + * Some properties of asinh(x) = log(x + sqrt(x^2 + 1)) + * 1) defined on ]-Infinity,+Infinity[ + * 2) result in ]-Infinity,+Infinity[ + * 3) asinh(x) = -asinh(-x) (implies asinh(0) = 0) + * 4) asinh(epsilon) ~= epsilon + * 5) lim(asinh(x),x->+Infinity) = +Infinity + * (y increasing logarithmically slower than x) + * + * @param value A double value. + * @return Value hyperbolic arcsine. + */ + public static double asinh(double value) { + // asinh(x) = log(x + sqrt(x^2 + 1)) + boolean negateResult = false; + if (value < 0.0) { + value = -value; + negateResult = true; + } + double result; + // (about) smallest possible for + // non-log1p case to be accurate. + if (value < ASINH_LOG1P_THRESHOLD) { + // Around this range, FDLIBM uses + // log1p(value+value*value/(1+sqrt(value*value+1))), + // but it's slower, so we don't use it. + /* + * If x is close to zero, log argument is close to 1, + * so to avoid precision loss we use log1p(double), + * with + * (1+x)^p = 1 + p * x + (p*(p-1))/2! * x^2 + (p*(p-1)*(p-2))/3! * x^3 + ... + * (1+x)^p = 1 + p * x * (1 + (p-1)/2 * x * (1 + (p-2)/3 * x + ...) + * (1+x)^0.5 = 1 + 0.5 * x * (1 + (0.5-1)/2 * x * (1 + (0.5-2)/3 * x + ...) + * (1+x^2)^0.5 = 1 + 0.5 * x^2 * (1 + (0.5-1)/2 * x^2 * (1 + (0.5-2)/3 * x^2 + ...) + * x + (1+x^2)^0.5 = 1 + x * (1 + 0.5 * x * (1 + (0.5-1)/2 * x^2 * (1 + (0.5-2)/3 * x^2 + ...)) + * so + * asinh(x) = log1p(x * (1 + 0.5 * x * (1 + (0.5-1)/2 * x^2 * (1 + (0.5-2)/3 * x^2 + ...))) + */ + final double x = value; + final double x2 = x*x; + // Enough terms for good accuracy, + // given our threshold. + final double argLog1p = (x * + (1 + 0.5 * x + * (1 + (0.5-1)/2 * x2 + * (1 + (0.5-2)/3 * x2 + * (1 + (0.5-3)/4 * x2 + * (1 + (0.5-4)/5 * x2 + )))))); + result = log1p(argLog1p); + } else if (value < ASINH_ACOSH_SQRT_ELISION_THRESHOLD) { + // Around this range, FDLIBM uses + // log(2*value+1/(value+sqrt(value*value+1))), + // but it involves an additional division + // so we don't use it. + result = log(value + sqrt(value*value + 1.0)); + } else { + // log(2*value) would overflow for value > Double.MAX_VALUE/2, + // so we compute otherwise. + result = LOG_2 + log(value); + } + return negateResult ? -result : result; + } + + /** + * Some properties of acosh(x) = log(x + sqrt(x^2 - 1)): + * 1) defined on [1,+Infinity[ + * 2) result in ]0,+Infinity[ (by convention, since cosh(x) = cosh(-x)) + * 3) acosh(1) = 0 + * 4) acosh(1+epsilon) ~= log(1 + sqrt(2*epsilon)) ~= sqrt(2*epsilon) + * 5) lim(acosh(x),x->+Infinity) = +Infinity + * (y increasing logarithmically slower than x) + * + * @param value A double value. + * @return Value hyperbolic arccosine. + */ + public static double acosh(double value) { + if (!(value > 1.0)) { + // NaN, or value <= 1 + if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { + return (value < 1.0) ? Double.NaN : value - 1.0; + } else { + return (value == 1.0) ? 0.0 : Double.NaN; + } + } + double result; + if (value < ASINH_ACOSH_SQRT_ELISION_THRESHOLD) { + // Around this range, FDLIBM uses + // log(2*value-1/(value+sqrt(value*value-1))), + // but it involves an additional division + // so we don't use it. + result = log(value + sqrt(value*value - 1.0)); + } else { + // log(2*value) would overflow for value > Double.MAX_VALUE/2, + // so we compute otherwise. + result = LOG_2 + log(value); + } + return result; + } + + /** + * Much more accurate than acosh(1+value), + * for arguments (and results) close to zero. + * + * acosh1p(-0.0) = -0.0, for homogeneity with + * sqrt(-0.0) = -0.0, which looks about the same + * near 0. + * + * @param value A double value. + * @return Hyperbolic arccosine of (1+value). + */ + public static double acosh1p(double value) { + if (!(value > 0.0)) { + // NaN, or value <= 0. + // If value is -0.0, returning -0.0. + if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { + return (value < 0.0) ? Double.NaN : value; + } else { + return (value == 0.0) ? value : Double.NaN; + } + } + double result; + if (value < (ASINH_ACOSH_SQRT_ELISION_THRESHOLD-1)) { + // acosh(1+x) + // = log((1+x) + sqrt((1+x)^2 - 1)) + // = log(1 + x + sqrt(1 + 2*x + x^2 - 1)) + // = log1p(x + sqrt(2*x + x^2)) + // = log1p(x + sqrt(x * (2 + x)) + result = log1p(value + sqrt(value * (2 + value))); + } else { + result = LOG_2 + log(1+value); + } + return result; + } + + /** + * Some properties of atanh(x) = log((1+x)/(1-x))/2: + * 1) defined on ]-1,1[ + * 2) result in ]-Infinity,+Infinity[ + * 3) atanh(-1) = -Infinity (by continuity) + * 4) atanh(1) = +Infinity (by continuity) + * 5) atanh(epsilon) ~= epsilon + * 6) lim(atanh(x),x->1) = +Infinity + * + * @param value A double value. + * @return Value hyperbolic arctangent. + */ + public static double atanh(double value) { + boolean negateResult = false; + if (value < 0.0) { + value = -value; + negateResult = true; + } + double result; + if (!(value < 1.0)) { + // NaN, or value >= 1 + if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { + result = (value > 1.0) ? Double.NaN : Double.POSITIVE_INFINITY + value; + } else { + result = (value == 1.0) ? Double.POSITIVE_INFINITY : Double.NaN; + } + } else { + // For value < 0.5, FDLIBM uses + // 0.5 * log1p((value+value) + (value+value)*value/(1-value)), + // instead, but this is good enough for us. + // atanh(x) + // = log((1+x)/(1-x))/2 + // = log((1-x+2x)/(1-x))/2 + // = log1p(2x/(1-x))/2 + result = 0.5 * log1p((value+value)/(1.0-value)); + } + return negateResult ? -result : result; + } + + /* + * exponentials + */ + + /** + * @param value A double value. + * @return e^value. + */ + public static double exp(double value) { + if (USE_JDK_MATH) { + return Math.exp(value); + } + // exp(x) = exp([x])*exp(y) + // with [x] the integer part of x, and y = x-[x] + // ===> + // We find an approximation of y, called z. + // ===> + // exp(x) = exp([x])*(exp(z)*exp(epsilon)) + // with epsilon = y - z + // ===> + // We have exp([x]) and exp(z) pre-computed in tables, we "just" have to compute exp(epsilon). + // + // We use the same indexing (cast to int) to compute x integer part and the + // table index corresponding to z, to avoid two int casts. + // Also, to optimize index multiplication and division, we use powers of two, + // so that we can do it with bits shifts. + + if (value > EXP_OVERFLOW_LIMIT) { + return Double.POSITIVE_INFINITY; + } else if (!(value >= EXP_UNDERFLOW_LIMIT)) { + return (value != value) ? Double.NaN : 0.0; + } + + final int indexes = (int)(value*EXP_LO_INDEXING); + + final int valueInt; + if (indexes >= 0) { + valueInt = (indexes>>EXP_LO_INDEXING_DIV_SHIFT); + } else { + valueInt = -((-indexes)>>EXP_LO_INDEXING_DIV_SHIFT); + } + final double hiTerm = MyTExp.expHiTab[valueInt-(int)EXP_UNDERFLOW_LIMIT]; + + final int zIndex = indexes - (valueInt< 0.0) { + if (value == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } + + // For normal values not close to 1.0, we use the following formula: + // log(value) + // = log(2^exponent*1.mantissa) + // = log(2^exponent) + log(1.mantissa) + // = exponent * log(2) + log(1.mantissa) + // = exponent * log(2) + log(1.mantissaApprox) + log(1.mantissa/1.mantissaApprox) + // = exponent * log(2) + log(1.mantissaApprox) + log(1+epsilon) + // = exponent * log(2) + log(1.mantissaApprox) + epsilon-epsilon^2/2+epsilon^3/3-epsilon^4/4+... + // with: + // 1.mantissaApprox <= 1.mantissa, + // log(1.mantissaApprox) in table, + // epsilon = (1.mantissa/1.mantissaApprox)-1 + // + // To avoid bad relative error for small results, + // values close to 1.0 are treated aside, with the formula: + // log(x) = z*(2+z^2*((2.0/3)+z^2*((2.0/5))+z^2*((2.0/7))+...))) + // with z=(x-1)/(x+1) + + double h; + if (value > 0.95) { + if (value < 1.14) { + double z = (value-1.0)/(value+1.0); + double z2 = z*z; + return z*(2+z2*((2.0/3)+z2*((2.0/5)+z2*((2.0/7)+z2*((2.0/9)+z2*((2.0/11))))))); + } + h = 0.0; + } else if (value < DOUBLE_MIN_NORMAL) { + // Ensuring value is normal. + value *= TWO_POW_52; + // log(x*2^52) + // = log(x)-ln(2^52) + // = log(x)-52*ln(2) + h = -52*LOG_2; + } else { + h = 0.0; + } + + int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); + int valueExp = (valueBitsHi>>20)-MAX_DOUBLE_EXPONENT; + // Getting the first LOG_BITS bits of the mantissa. + int xIndex = ((valueBitsHi<<12)>>>(32-LOG_BITS)); + + // 1.mantissa/1.mantissaApprox - 1 + double z = (value * twoPowNormalOrSubnormal(-valueExp)) * MyTLog.logXInvTab[xIndex] - 1; + + z *= (1-z*((1.0/2)-z*((1.0/3)))); + + return h + valueExp * LOG_2 + (MyTLog.logXLogTab[xIndex] + z); + + } else if (value == 0.0) { + return Double.NEGATIVE_INFINITY; + } else { // value < 0.0, or value is NaN + return Double.NaN; + } + } + + /** + * Quick log, with a max relative error of about 1.9e-3 + * for values in ]Double.MIN_NORMAL,+Infinity[, and + * worse accuracy outside this range. + * + * @param value A double value, in ]0,+Infinity[ (strictly positive and finite). + * @return Value logarithm (base e). + */ + public static double logQuick(double value) { + if (USE_JDK_MATH) { + return Math.log(value); + } + /* + * Inverse of Schraudolph's method for exp, is very inaccurate near 1, + * and not that fast (even using floats), especially with added if's + * to deal with values near 1, so we don't use it, and use a simplified + * version of our log's redefined algorithm. + */ + + // Simplified version of log's redefined algorithm: + // log(value) ~= exponent * log(2) + log(1.mantissaApprox) + + double h; + if (value > 0.87) { + if (value < 1.16) { + return 2.0 * (value-1.0)/(value+1.0); + } + h = 0.0; + } else if (value < DOUBLE_MIN_NORMAL) { + value *= TWO_POW_52; + h = -52*LOG_2; + } else { + h = 0.0; + } + + int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); + int valueExp = (valueBitsHi>>20)-MAX_DOUBLE_EXPONENT; + int xIndex = ((valueBitsHi<<12)>>>(32-LOG_BITS)); + + return h + valueExp * LOG_2 + MyTLog.logXLogTab[xIndex]; + } + + /** + * @param value A double value. + * @return Value logarithm (base 10). + */ + public static double log10(double value) { + if (USE_JDK_MATH || (!USE_REDEFINED_LOG)) { + return Math.log10(value); + } + // INV_LOG_10 is < 1, but there is no risk of log(double) + // overflow (positive or negative) while the end result shouldn't, + // since log(Double.MIN_VALUE) and log(Double.MAX_VALUE) have + // magnitudes of just a few hundreds. + return log(value) * INV_LOG_10; + } + + /** + * Much more accurate than log(1+value), + * for arguments (and results) close to zero. + * + * @param value A double value. + * @return Logarithm (base e) of (1+value). + */ + public static double log1p(double value) { + if (USE_JDK_MATH) { + return Math.log1p(value); + } + if (false) { + // This also works. Simpler but a bit slower. + if (value == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } + double valuePlusOne = 1+value; + if (valuePlusOne == 1.0) { + return value; + } else { + return log(valuePlusOne)*(value/(valuePlusOne-1.0)); + } + } + if (value > -1.0) { + if (value == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } + + // ln'(x) = 1/x + // so + // log(x+epsilon) ~= log(x) + epsilon/x + // + // Let u be 1+value rounded: + // 1+value = u+epsilon + // + // log(1+value) + // = log(u+epsilon) + // ~= log(u) + epsilon/value + // We compute log(u) as done in log(double), and then add the corrective term. + + double valuePlusOne = 1.0+value; + if (valuePlusOne == 1.0) { + return value; + } else if (Math.abs(value) < 0.15) { + double z = value/(value+2.0); + double z2 = z*z; + return z*(2+z2*((2.0/3)+z2*((2.0/5)+z2*((2.0/7)+z2*((2.0/9)+z2*((2.0/11))))))); + } + + int valuePlusOneBitsHi = (int)(Double.doubleToRawLongBits(valuePlusOne)>>32) & 0x7FFFFFFF; + int valuePlusOneExp = (valuePlusOneBitsHi>>20)-MAX_DOUBLE_EXPONENT; + // Getting the first LOG_BITS bits of the mantissa. + int xIndex = ((valuePlusOneBitsHi<<12)>>>(32-LOG_BITS)); + + // 1.mantissa/1.mantissaApprox - 1 + double z = (valuePlusOne * twoPowNormalOrSubnormal(-valuePlusOneExp)) * MyTLog.logXInvTab[xIndex] - 1; + + z *= (1-z*((1.0/2)-z*(1.0/3))); + + // Adding epsilon/valuePlusOne to z, + // with + // epsilon = value - (valuePlusOne-1) + // (valuePlusOne + epsilon ~= 1+value (not rounded)) + + return valuePlusOneExp * LOG_2 + MyTLog.logXLogTab[xIndex] + (z + (value - (valuePlusOne-1))/valuePlusOne); + } else if (value == -1.0) { + return Double.NEGATIVE_INFINITY; + } else { // value < -1.0, or value is NaN + return Double.NaN; + } + } + + /* + * powers + */ + + /** + * 1e-13ish accuracy or better on whole double range. + * + * @param value A double value. + * @param power A power. + * @return value^power. + */ + public static double pow(double value, double power) { + if (USE_JDK_MATH) { + return Math.pow(value,power); + } + if (power == 0.0) { + return 1.0; + } else if (power == 1.0) { + return value; + } + if (value <= 0.0) { + // powerInfo: 0 if not integer, 1 if even integer, -1 if odd integer + int powerInfo; + if (Math.abs(power) >= (TWO_POW_52*2)) { + // The binary digit just before comma is outside mantissa, + // thus it is always 0: power is an even integer. + powerInfo = 1; + } else { + // If power's magnitude permits, we cast into int instead of into long, + // as it is faster. + if (Math.abs(power) <= (double)Integer.MAX_VALUE) { + int powerAsInt = (int)power; + if (power == (double)powerAsInt) { + powerInfo = ((powerAsInt & 1) == 0) ? 1 : -1; + } else { // power is not an integer (and not NaN, due to test against Integer.MAX_VALUE) + powerInfo = 0; + } + } else { + long powerAsLong = (long)power; + if (power == (double)powerAsLong) { + powerInfo = ((powerAsLong & 1) == 0) ? 1 : -1; + } else { // power is not an integer, or is NaN + if (power != power) { + return Double.NaN; + } + powerInfo = 0; + } + } + } + + if (value == 0.0) { + if (power < 0.0) { + return (powerInfo < 0) ? 1/value : Double.POSITIVE_INFINITY; + } else { // power > 0.0 (0 and NaN cases already treated) + return (powerInfo < 0) ? value : 0.0; + } + } else { // value < 0.0 + if (value == Double.NEGATIVE_INFINITY) { + if (powerInfo < 0) { // power odd integer + return (power < 0.0) ? -0.0 : Double.NEGATIVE_INFINITY; + } else { // power even integer, or not an integer + return (power < 0.0) ? 0.0 : Double.POSITIVE_INFINITY; + } + } else { + return (powerInfo == 0) ? Double.NaN : powerInfo * exp(power*log(-value)); + } + } + } else { // value > 0.0, or value is NaN + return exp(power*log(value)); + } + } + + /** + * Quick pow, with a max relative error of about 1e-2 + * for value >= Double.MIN_NORMAL and 1e-10 < |value^power| < 1e10, + * of about 6e-2 for value >= Double.MIN_NORMAL and 1e-40 < |value^power| < 1e40, + * and worse accuracy otherwise. + * + * @param value A double value, in ]0,+Infinity[ (strictly positive and finite). + * @param power A double value. + * @return value^power. + */ + public static double powQuick(double value, double power) { + if (USE_JDK_MATH) { + return Math.pow(value,power); + } + return exp(power*logQuick(value)); + } + + /** + * This treatment is somehow accurate for low values of |power|, + * and for |power*getExponent(value)| < 1023 or so (to stay away + * from double extreme magnitudes (large and small)). + * + * @param value A double value. + * @param power A power. + * @return value^power. + */ + public static double powFast(double value, int power) { + if (USE_JDK_MATH) { + return Math.pow(value,power); + } + if (power < 3) { + if (power < 0) { + // Opposite of Integer.MIN_VALUE does not exist as int. + if (power == Integer.MIN_VALUE) { + // Integer.MAX_VALUE = -(power+1) + return 1.0/(powFast(value,Integer.MAX_VALUE) * value); + } else { + return 1.0/powFast(value,-power); + } + } else { + // Here, power is in [0,2]. + if (power == 2) { // Most common case first. + return value * value; + } else if (power == 0) { + return 1.0; + } else { // power == 1 + return value; + } + } + } else { // power >= 4 + double oddRemains = 1.0; + // If power <= 5, faster to finish outside the loop. + while (power > 5) { + // Test if power is odd. + if ((power & 1) != 0) { + oddRemains *= value; + } + value *= value; + power >>= 1; // power = power / 2 + } + // Here, power is in [3,5]. + if (power == 3) { + return oddRemains * value * value * value; + } else { // power in [4,5]. + double v2 = value * value; + if (power == 4) { + return oddRemains * v2 * v2; + } else { // power == 5 + return oddRemains * v2 * v2 * value; + } + } + } + } + + /** + * @param value A float value. + * @return value*value. + */ + public static float pow2(float value) { + return value*value; + } + + /** + * @param value A double value. + * @return value*value. + */ + public static double pow2(double value) { + return value*value; + } + + /** + * @param value A float value. + * @return value*value*value. + */ + public static float pow3(float value) { + return value*value*value; + } + + /** + * @param value A double value. + * @return value*value*value. + */ + public static double pow3(double value) { + return value*value*value; + } + + /* + * roots + */ + + /** + * @param value A double value. + * @return Value square root. + */ + public static double sqrt(double value) { + if (USE_JDK_MATH || (!USE_REDEFINED_SQRT)) { + return Math.sqrt(value); + } + // See cbrt for comments, sqrt uses the same ideas. + + if (!(value > 0.0)) { // value <= 0.0, or value is NaN + if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { + return (value < 0.0) ? Double.NaN : value; + } else { + return (value == 0.0) ? value : Double.NaN; + } + } else if (value == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } + + double h; + if (value < DOUBLE_MIN_NORMAL) { + value *= TWO_POW_52; + h = 2*TWO_POW_N26; + } else { + h = 2.0; + } + + int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); + int valueExponentIndex = (valueBitsHi>>20)+(-MAX_DOUBLE_EXPONENT-MIN_DOUBLE_EXPONENT); + int xIndex = ((valueBitsHi<<12)>>>(32-SQRT_LO_BITS)); + + double result = MyTSqrt.sqrtXSqrtHiTab[valueExponentIndex] * MyTSqrt.sqrtXSqrtLoTab[xIndex]; + double slope = MyTSqrt.sqrtSlopeHiTab[valueExponentIndex] * MyTSqrt.sqrtSlopeLoTab[xIndex]; + value *= 0.25; + + result += (value - result * result) * slope; + result += (value - result * result) * slope; + return h*(result + (value - result * result) * slope); + } + + /** + * Quick sqrt, with with a max relative error of about 3.41e-2 + * for values in [Double.MIN_NORMAL,Double.MAX_VALUE], and worse + * accuracy outside this range. + * + * @param value A double value. + * @return Value square root. + */ + public static double sqrtQuick(double value) { + if (USE_JDK_MATH) { + return Math.sqrt(value); + } + final long bits = Double.doubleToRawLongBits(value); + /* + * Constant determined empirically, using a random-based metaheuristic. + * Should be possible to find a better one. + */ + return Double.longBitsToDouble((bits+4606859074900000000L)>>>1); + } + + /** + * Quick inverse of square root, with a max relative error of about 3.44e-2 + * for values in [Double.MIN_NORMAL,Double.MAX_VALUE], and worse accuracy + * outside this range. + * + * This implementation uses zero step of Newton's method. + * Here are the max relative errors on [Double.MIN_NORMAL,Double.MAX_VALUE] + * depending on number of steps, if you want to copy-paste this code + * and use your own number: + * n=0: about 3.44e-2 + * n=1: about 1.75e-3 + * n=2: about 4.6e-6 + * n=3: about 3.17e-11 + * n=4: about 3.92e-16 + * n=5: about 3.03e-16 + * + * @param value A double value. + * @return Inverse of value square root. + */ + public static double invSqrtQuick(double value) { + if (USE_JDK_MATH) { + return 1/Math.sqrt(value); + } + /* + * http://en.wikipedia.org/wiki/Fast_inverse_square_root + */ + if (false) { + // With one Newton step (much slower than + // 1/Math.sqrt(double) if not optimized). + final double halfInitial = value * 0.5; + long bits = Double.doubleToRawLongBits(value); + // If n=0, 6910474759270000000L might be better (3.38e-2 max relative error). + bits = 0x5FE6EB50C7B537A9L - (bits>>1); + value = Double.longBitsToDouble(bits); + value = value * (1.5 - halfInitial * value * value); // Newton step, can repeat. + return value; + } else { + return Double.longBitsToDouble(0x5FE6EB50C7B537A9L - (Double.doubleToRawLongBits(value)>>1)); + } + } + + /** + * @param value A double value. + * @return Value cubic root. + */ + public static double cbrt(double value) { + if (USE_JDK_MATH) { + return Math.cbrt(value); + } + double h; + if (value < 0.0) { + if (value == Double.NEGATIVE_INFINITY) { + return Double.NEGATIVE_INFINITY; + } + value = -value; + // Making sure value is normal. + if (value < DOUBLE_MIN_NORMAL) { + value *= (TWO_POW_52*TWO_POW_26); + // h = * / + h = -2*TWO_POW_N26; + } else { + h = -2.0; + } + } else { + if (!(value < Double.POSITIVE_INFINITY)) { // value is +Infinity, or value is NaN + return value; + } + // Making sure value is normal. + if (value < DOUBLE_MIN_NORMAL) { + if (value == 0.0) { + // cbrt(0.0) = 0.0, cbrt(-0.0) = -0.0 + return value; + } + value *= (TWO_POW_52*TWO_POW_26); + h = 2*TWO_POW_N26; + } else { + h = 2.0; + } + } + + // Normal value is (2^ *
). + // First member cubic root is computed, and multiplied with an approximation + // of the cubic root of the second member, to end up with a good guess of + // the result before using Newton's (or Archimedes's) method. + // To compute the cubic root approximation, we use the formula "cbrt(value) = cbrt(x) * cbrt(value/x)", + // choosing x as close to value as possible but inferior to it, so that cbrt(value/x) is close to 1 + // (we could iterate on this method, using value/x as new value for each iteration, + // but finishing with Newton's method is faster). + + // Shift and cast into an int, which overall is faster than working with a long. + int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); + int valueExponentIndex = (valueBitsHi>>20)+(-MAX_DOUBLE_EXPONENT-MIN_DOUBLE_EXPONENT); + // Getting the first CBRT_LO_BITS bits of the mantissa. + int xIndex = ((valueBitsHi<<12)>>>(32-CBRT_LO_BITS)); + double result = MyTCbrt.cbrtXCbrtHiTab[valueExponentIndex] * MyTCbrt.cbrtXCbrtLoTab[xIndex]; + double slope = MyTCbrt.cbrtSlopeHiTab[valueExponentIndex] * MyTCbrt.cbrtSlopeLoTab[xIndex]; + + // Lowering values to avoid overflows when using Newton's method + // (we will then just have to return twice the result). + // result^3 = value + // (result/2)^3 = value/8 + value *= 0.125; + // No need to divide result here, as division is factorized in result computation tables. + // result *= 0.5; + + // Newton's method, looking for y = x^(1/p): + // y(n) = y(n-1) + (x-y(n-1)^p) * slope(y(n-1)) + // y(n) = y(n-1) + (x-y(n-1)^p) * (1/p)*(x(n-1)^(1/p-1)) + // y(n) = y(n-1) + (x-y(n-1)^p) * (1/p)*(x(n-1)^((1-p)/p)) + // with x(n-1)=y(n-1)^p, i.e.: + // y(n) = y(n-1) + (x-y(n-1)^p) * (1/p)*(y(n-1)^(1-p)) + // + // For p=3: + // y(n) = y(n-1) + (x-y(n-1)^3) * (1/(3*y(n-1)^2)) + + // To save time, we don't recompute the slope between Newton's method steps, + // as initial slope is good enough for a few iterations. + // + // NB: slope = 1/(3*trueResult*trueResult) + // As we have result = trueResult/2 (to avoid overflows), we have: + // slope = 4/(3*result*result) + // = (4/3)*resultInv*resultInv + // with newResultInv = 1/newResult + // = 1/(oldResult+resultDelta) + // = (oldResultInv)*1/(1+resultDelta/oldResult) + // = (oldResultInv)*1/(1+resultDelta*oldResultInv) + // ~= (oldResultInv)*(1-resultDelta*oldResultInv) + // ===> Successive slopes could be computed without division, if needed, + // by computing resultInv (instead of slope right away) and retrieving + // slopes from it. + + result += (value - result * result * result) * slope; + result += (value - result * result * result) * slope; + return h*(result + (value - result * result * result) * slope); + } + + /** + * @return sqrt(x^2+y^2) without intermediate overflow or underflow. + */ + public static double hypot(double x, double y) { + if (USE_JDK_MATH) { + return Math.hypot(x,y); + } + x = Math.abs(x); + y = Math.abs(y); + // Ensuring x <= y. + if (y < x) { + double a = x; + x = y; + y = a; + } else if (!(y >= x)) { // Testing if we have some NaN. + return hypot_NaN(x, y); + } + + if (y-x == y) { + // x too small to subtract from y. + return y; + } else { + double factor; + if (y > HYPOT_MAX_MAG) { + // y is too large: scaling down. + x *= (1/HYPOT_FACTOR); + y *= (1/HYPOT_FACTOR); + factor = HYPOT_FACTOR; + } else if (x < (1/HYPOT_MAX_MAG)) { + // x is too small: scaling up. + x *= HYPOT_FACTOR; + y *= HYPOT_FACTOR; + factor = (1/HYPOT_FACTOR); + } else { + factor = 1.0; + } + return factor * sqrt(x*x+y*y); + } + } + + /** + * @return sqrt(x^2+y^2+z^2) without intermediate overflow or underflow. + */ + public static double hypot(double x, double y, double z) { + if (USE_JDK_MATH) { + // No simple JDK equivalent. + } + x = Math.abs(x); + y = Math.abs(y); + z = Math.abs(z); + /* + * Considering that z magnitude is the most likely to be the smaller, + * hence ensuring z <= y <= x, and not x <= y <= z, for less swaps. + */ + // Ensuring z <= y. + if (z > y) { + // y < z: swapping y and z + double a = z; + z = y; + y = a; + } else if (!(z <= y)) { // Testing if y or z is NaN. + return hypot_NaN(x, y, z); + } + // Ensuring y <= x. + if (z > x) { + // x < z <= y: moving x + double oldZ = z; + z = x; + double oldY = y; + y = oldZ; + x = oldY; + } else if (y > x) { + // z <= x < y: swapping x and y + double a = y; + y = x; + x = a; + } else if (x != x) { // Testing if x is NaN. + return hypot_NaN(x, y, z); + } + + if (x-y == x) { + // y, hence z, too small to subtract from x. + return x; + } else if (y-z == y) { + // z too small to subtract from y, hence x. + double factor; + if (x > HYPOT_MAX_MAG) { + // x is too large: scaling down. + x *= (1/HYPOT_FACTOR); + y *= (1/HYPOT_FACTOR); + factor = HYPOT_FACTOR; + } else if (y < (1/HYPOT_MAX_MAG)) { + // y is too small: scaling up. + x *= HYPOT_FACTOR; + y *= HYPOT_FACTOR; + factor = (1/HYPOT_FACTOR); + } else { + factor = 1.0; + } + return factor * sqrt(x*x+y*y); + } else { + double factor; + if (x > HYPOT_MAX_MAG) { + // x is too large: scaling down. + x *= (1/HYPOT_FACTOR); + y *= (1/HYPOT_FACTOR); + z *= (1/HYPOT_FACTOR); + factor = HYPOT_FACTOR; + } else if (z < (1/HYPOT_MAX_MAG)) { + // z is too small: scaling up. + x *= HYPOT_FACTOR; + y *= HYPOT_FACTOR; + z *= HYPOT_FACTOR; + factor = (1/HYPOT_FACTOR); + } else { + factor = 1.0; + } + // Adding smaller magnitudes together first. + return factor * sqrt(x*x+(y*y+z*z)); + } + } + + /* + * close values + */ + + /** + * @param value A float value. + * @return Floor of value. + */ + public static float floor(float value) { + final int exponent = getExponent(value); + if (exponent < 0) { + // abs(value) < 1. + if (value < 0.0f) { + return -1.0f; + } else { + // 0.0f, or -0.0f if value is -0.0f + return 0.0f * value; + } + } else if (exponent < 23) { + // A bit faster than using casts. + final int bits = Float.floatToRawIntBits(value); + final int anteCommaBits = bits & (0xFF800000>>exponent); + if ((value < 0.0f) && (anteCommaBits != bits)) { + return Float.intBitsToFloat(anteCommaBits) - 1.0f; + } else { + return Float.intBitsToFloat(anteCommaBits); + } + } else { + // +-Infinity, NaN, or a mathematical integer. + return value; + } + } + + /** + * @param value A double value. + * @return Floor of value. + */ + public static double floor(double value) { + if (USE_JDK_MATH) { + return Math.floor(value); + } + if (ANTI_SLOW_CASTS) { + double valueAbs = Math.abs(value); + if (valueAbs <= (double)Integer.MAX_VALUE) { + if (value > 0.0) { + return (double)(int)value; + } else if (value < 0.0) { + double anteCommaDigits = (double)(int)value; + if (value != anteCommaDigits) { + return anteCommaDigits - 1.0; + } else { + return anteCommaDigits; + } + } else { // value is +-0.0 (not NaN due to test against Integer.MAX_VALUE) + return value; + } + } else if (valueAbs < TWO_POW_52) { + // We split the value in two: + // high part, which is a mathematical integer, + // and the rest, for which we can get rid of the + // post comma digits by casting into an int. + double highPart = ((int)(value * TWO_POW_N26)) * TWO_POW_26; + if (value > 0.0) { + return highPart + (double)((int)(value - highPart)); + } else { + double anteCommaDigits = highPart + (double)((int)(value - highPart)); + if (value != anteCommaDigits) { + return anteCommaDigits - 1.0; + } else { + return anteCommaDigits; + } + } + } else { // abs(value) >= 2^52, or value is NaN + return value; + } + } else { + final int exponent = getExponent(value); + if (exponent < 0) { + // abs(value) < 1. + if (value < 0.0) { + return -1.0; + } else { + // 0.0, or -0.0 if value is -0.0 + return 0.0 * value; + } + } else if (exponent < 52) { + // A bit faster than working on bits. + final long matIntPart = (long)value; + final double matIntToValue = value-(double)matIntPart; + if (matIntToValue >= 0.0) { + return (double)matIntPart; + } else { + return (double)(matIntPart - 1); + } + } else { + // +-Infinity, NaN, or a mathematical integer. + return value; + } + } + } + + /** + * @param value A float value. + * @return Ceiling of value. + */ + public static float ceil(float value) { + return -floor(-value); + } + + /** + * @param value A double value. + * @return Ceiling of value. + */ + public static double ceil(double value) { + if (USE_JDK_MATH) { + return Math.ceil(value); + } + return -floor(-value); + } + + /** + * Might have different semantics than Math.round(float), + * see bugs 6430675 and 8010430. + * + * @param value A double value. + * @return Value rounded to nearest int, choosing superior int in case two + * are equally close (i.e. rounding-up). + */ + public static int round(float value) { + /* + * Not delegating to JDK, because we want delegation to provide + * at least as good results, and some supported JDK versions + * have bugged round() methods. + */ + // Algorithm by Dmitry Nadezhin (but replaced an if by a multiply) + // (http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-August/020247.html). + final int bits = Float.floatToRawIntBits(value); + final int biasedExp = ((bits>>23)&0xFF); + // Shift to get rid of bits past comma except first one: will need to + // 1-shift to the right to end up with correct magnitude. + final int shift = (23 - 1 + MAX_FLOAT_EXPONENT) - biasedExp; + if ((shift & -32) == 0) { + int bitsSignum = (((bits >> 31) << 1) + 1); + // shift in [0,31], so unbiased exp in [-9,22]. + int extendedMantissa = (0x00800000 | (bits & 0x007FFFFF)) * bitsSignum; + // If value is positive and first bit past comma is 0, rounding + // to lower integer, else to upper one, which is what "+1" and + // then ">>1" do. + return ((extendedMantissa >> shift) + 1) >> 1; + } else { + // +-Infinity, NaN, or a mathematical integer, or tiny. + if (false && ANTI_SLOW_CASTS) { // not worth it + if (Math.abs(value) >= -(float)Integer.MIN_VALUE) { + // +-Infinity or a mathematical integer (mostly) out of int range. + return (value < 0.0) ? Integer.MIN_VALUE : Integer.MAX_VALUE; + } + // NaN or a mathematical integer (mostly) in int range. + } + return (int)value; + } + } + + /** + * Might have different semantics than Math.round(double), + * see bugs 6430675 and 8010430. + * + * @param value A double value. + * @return Value rounded to nearest long, choosing superior long in case two + * are equally close (i.e. rounding-up). + */ + public static long round(double value) { + /* + * Not delegating to JDK, because we want delegation to provide + * at least as good results, and some supported JDK versions + * have bugged round() methods. + */ + final long bits = Double.doubleToRawLongBits(value); + final int biasedExp = (((int)(bits>>52))&0x7FF); + // Shift to get rid of bits past comma except first one: will need to + // 1-shift to the right to end up with correct magnitude. + final int shift = (52 - 1 + MAX_DOUBLE_EXPONENT) - biasedExp; + if ((shift & -64) == 0) { + long bitsSignum = (((bits >> 63) << 1) + 1); + // shift in [0,63], so unbiased exp in [-12,51]. + long extendedMantissa = (0x0010000000000000L | (bits & 0x000FFFFFFFFFFFFFL)) * bitsSignum; + // If value is positive and first bit past comma is 0, rounding + // to lower integer, else to upper one, which is what "+1" and + // then ">>1" do. + return ((extendedMantissa >> shift) + 1L) >> 1; + } else { + // +-Infinity, NaN, or a mathematical integer, or tiny. + if (ANTI_SLOW_CASTS) { + if (Math.abs(value) >= -(double)Long.MIN_VALUE) { + // +-Infinity or a mathematical integer (mostly) out of long range. + return (value < 0.0) ? Long.MIN_VALUE : Long.MAX_VALUE; + } + // NaN or a mathematical integer (mostly) in long range. + } + return (long)value; + } + } + + /** + * @param value A float value. + * @return Value rounded to nearest int, choosing even int in case two + * are equally close. + */ + public static int roundEven(float value) { + final int sign = signFromBit(value); + value = Math.abs(value); + if (ANTI_SLOW_CASTS) { + if (value < TWO_POW_23_F) { + // Getting rid of post-comma bits. + value = ((value + TWO_POW_23_F) - TWO_POW_23_F); + return sign * (int)value; + } else if (value < (float)Integer.MAX_VALUE) { // "<=" doesn't work, because of float precision + // value is in [-Integer.MAX_VALUE,Integer.MAX_VALUE] + return sign * (int)value; + } + } else { + if (value < TWO_POW_23_F) { + // Getting rid of post-comma bits. + value = ((value + TWO_POW_23_F) - TWO_POW_23_F); + } + } + return (int)(sign * value); + } + + /** + * @param value A double value. + * @return Value rounded to nearest long, choosing even long in case two + * are equally close. + */ + public static long roundEven(double value) { + final int sign = (int)signFromBit(value); + value = Math.abs(value); + if (value < TWO_POW_52) { + // Getting rid of post-comma bits. + value = ((value + TWO_POW_52) - TWO_POW_52); + } + if (ANTI_SLOW_CASTS) { + if (value <= (double)Integer.MAX_VALUE) { + // value is in [-Integer.MAX_VALUE,Integer.MAX_VALUE] + return sign * (int)value; + } + } + return (long)(sign * value); + } + + /** + * @param value A float value. + * @return The float mathematical integer closest to the specified value, + * choosing even one if two are equally close, or respectively + * NaN, +-Infinity or +-0.0f if the value is any of these. + */ + public static float rint(float value) { + final int sign = signFromBit(value); + value = Math.abs(value); + if (value < TWO_POW_23_F) { + // Getting rid of post-comma bits. + value = ((TWO_POW_23_F + value ) - TWO_POW_23_F); + } + // Restoring original sign. + return sign * value; + } + + /** + * @param value A double value. + * @return The double mathematical integer closest to the specified value, + * choosing even one if two are equally close, or respectively + * NaN, +-Infinity or +-0.0 if the value is any of these. + */ + public static double rint(double value) { + if (USE_JDK_MATH) { + return Math.rint(value); + } + final int sign = (int)signFromBit(value); + value = Math.abs(value); + if (value < TWO_POW_52) { + // Getting rid of post-comma bits. + value = ((TWO_POW_52 + value ) - TWO_POW_52); + } + // Restoring original sign. + return sign * value; + } + + /* + * close int values + * + * Never delegating to JDK for these methods, for we should always + * be faster and exact, and JDK doesn't exactly have such methods. + */ + + /** + * @param value A double value. + * @return Floor of value as int, or closest int if floor is out + * of int range, or 0 if value is NaN. + */ + public static int floorToInt(double value) { + int valueInt = (int) value; + if (value < 0.0) { + if (value == (double) valueInt) { + return valueInt; + } else { + if (valueInt == Integer.MIN_VALUE) { + return valueInt; + } else { + return valueInt - 1; + } + } + } else { // >= 0 or NaN. + return valueInt; + } + } + + /** + * @param value A double value. + * @return Ceiling of value as int, or closest int if ceiling is out + * of int range, or 0 if value is NaN. + */ + public static int ceilToInt(double value) { + int valueInt = (int) value; + if (value > 0.0) { + if (value == (double) valueInt) { + return valueInt; + } else { + if (valueInt == Integer.MAX_VALUE) { + return valueInt; + } else { + return valueInt + 1; + } + } + } else { // <= 0 or NaN. + return valueInt; + } + } + + /** + * @param value A double value. + * @return Value rounded to nearest int, choosing superior int in case two + * are equally close (i.e. rounding-up). + */ + public static int roundToInt(double value) { + /* + * We don't gain much by reimplementing rounding, except for + * pathologically large values, which should not be a common case + * when dealing with ints, so we just use round(double). + */ + return NumbersUtils.toInt(round(value)); + } + + /** + * @param value A double value. + * @return Value rounded to nearest int, choosing even int in case two + * are equally close. + */ + public static int roundEvenToInt(double value) { + final int sign = (int)signFromBit(value); + value = Math.abs(value); + /* + * Applying the post-comma bits removal logic even if value is out + * of int range, to avoid a test, for it doesn't mess up the result, + * and we want to optimize for the case of values in int range. + */ + value = ((value + TWO_POW_52) - TWO_POW_52); + return (int)(sign * value); + } + + /* + * ranges + */ + + /** + * @param min A float value. + * @param max A float value. + * @param value A float value. + * @return min if value < min, max if value > max, value otherwise. + */ + public static float toRange(float min, float max, float value) { + return NumbersUtils.toRange(min, max, value); + } + + /** + * @param min A double value. + * @param max A double value. + * @param value A double value. + * @return min if value < min, max if value > max, value otherwise. + */ + public static double toRange(double min, double max, double value) { + return NumbersUtils.toRange(min, max, value); + } + + /* + * binary operators (/,%) + */ + + /** + * Returns dividend - divisor * n, where n is the mathematical integer + * closest to dividend/divisor. + * If dividend/divisor is equally close to surrounding integers, + * we choose n to be the integer of smallest magnitude, which makes + * this treatment differ from Math.IEEEremainder(double,double), + * where n is chosen to be the even integer. + * Note that the choice of n is not done considering the double + * approximation of dividend/divisor, because it could cause + * result to be outside [-|divisor|/2,|divisor|/2] range. + * The practical effect is that if multiple results would be possible, + * we always choose the result that is the closest to (and has the same + * sign as) the dividend. + * Ex. : + * - for (-3.0,2.0), this method returns -1.0, + * whereas Math.IEEEremainder returns 1.0. + * - for (-5.0,2.0), both this method and Math.IEEEremainder return -1.0. + * + * If the remainder is zero, its sign is the same as the sign of the first argument. + * If either argument is NaN, or the first argument is infinite, + * or the second argument is positive zero or negative zero, + * then the result is NaN. + * If the first argument is finite and the second argument is + * infinite, then the result is the same as the first argument. + * + * NB: + * - Modulo operator (%) returns a value in ]-|divisor|,|divisor|[, + * which sign is the same as dividend. + * - As for modulo operator, the sign of the divisor has no effect on the result. + * - On some architecture, % operator has been observed to return NaN + * for some subnormal values of divisor, when dividend exponent is 1023, + * which impacts the correctness of this method. + * + * @param dividend Dividend. + * @param divisor Divisor. + * @return Remainder of dividend/divisor, i.e. a value in [-|divisor|/2,|divisor|/2]. + */ + public static double remainder(double dividend, double divisor) { + if (Double.isInfinite(divisor)) { + if (Double.isInfinite(dividend)) { + return Double.NaN; + } else { + return dividend; + } + } + double value = dividend % divisor; + if (Math.abs(value+value) > Math.abs(divisor)) { + return value + ((value > 0.0) ? -Math.abs(divisor) : Math.abs(divisor)); + } else { + return value; + } + } + + /** + * @param angle Angle in radians. + * @return The same angle, in radians, but in [-PI,PI]. + */ + public static double normalizeMinusPiPi(double angle) { + // Not modifying values in output range. + if ((angle >= -Math.PI) && (angle <= Math.PI)) { + return angle; + } + return remainderTwoPi(angle); + } + + /** + * Not accurate for large values. + * + * @param angle Angle in radians. + * @return The same angle, in radians, but in [-PI,PI]. + */ + public static double normalizeMinusPiPiFast(double angle) { + // Not modifying values in output range. + if ((angle >= -Math.PI) && (angle <= Math.PI)) { + return angle; + } + return remainderTwoPiFast(angle); + } + + /** + * @param angle Angle in radians. + * @return The same angle, in radians, but in [0,2*PI]. + */ + public static double normalizeZeroTwoPi(double angle) { + // Not modifying values in output range. + if ((angle >= 0.0) && (angle <= 2*Math.PI)) { + return angle; + } + angle = remainderTwoPi(angle); + if (angle < 0.0) { + // LO then HI is theoretically better (when starting near 0). + return (angle + TWOPI_LO) + TWOPI_HI; + } else { + return angle; + } + } + + /** + * Not accurate for large values. + * + * @param angle Angle in radians. + * @return The same angle, in radians, but in [0,2*PI]. + */ + public static double normalizeZeroTwoPiFast(double angle) { + // Not modifying values in output range. + if ((angle >= 0.0) && (angle <= 2*Math.PI)) { + return angle; + } + angle = remainderTwoPiFast(angle); + if (angle < 0.0) { + // LO then HI is theoretically better (when starting near 0). + return (angle + TWOPI_LO) + TWOPI_HI; + } else { + return angle; + } + } + + /** + * @param angle Angle in radians. + * @return Angle value modulo PI, in radians, in [-PI/2,PI/2]. + */ + public static double normalizeMinusHalfPiHalfPi(double angle) { + // Not modifying values in output range. + if ((angle >= -Math.PI/2) && (angle <= Math.PI/2)) { + return angle; + } + return remainderPi(angle); + } + + /** + * Not accurate for large values. + * + * @param angle Angle in radians. + * @return Angle value modulo PI, in radians, in [-PI/2,PI/2]. + */ + public static double normalizeMinusHalfPiHalfPiFast(double angle) { + // Not modifying values in output range. + if ((angle >= -Math.PI/2) && (angle <= Math.PI/2)) { + return angle; + } + return remainderPiFast(angle); + } + + /* + * floating points utils + */ + + /** + * @param value A float value. + * @return true if the specified value is NaN or +-Infinity, false otherwise. + */ + public static boolean isNaNOrInfinite(float value) { + return NumbersUtils.isNaNOrInfinite(value); + } + + /** + * @param value A double value. + * @return true if the specified value is NaN or +-Infinity, false otherwise. + */ + public static boolean isNaNOrInfinite(double value) { + return NumbersUtils.isNaNOrInfinite(value); + } + + /** + * @param value A float value. + * @return Value unbiased exponent. + */ + public static int getExponent(float value) { + return ((Float.floatToRawIntBits(value)>>23)&0xFF)-MAX_FLOAT_EXPONENT; + } + + /** + * @param value A double value. + * @return Value unbiased exponent. + */ + public static int getExponent(double value) { + return (((int)(Double.doubleToRawLongBits(value)>>52))&0x7FF)-MAX_DOUBLE_EXPONENT; + } + + /** + * @param value A float value. + * @return -1.0f if the specified value is < 0, 1.0f if it is > 0, + * and the value itself if it is NaN or +-0.0f. + */ + public static float signum(float value) { + if (USE_JDK_MATH) { + return Math.signum(value); + } + if ((value == 0.0f) || (value != value)) { + return value; + } + return (float)signFromBit(value); + } + + /** + * @param value A double value. + * @return -1.0 if the specified value is < 0, 1.0 if it is > 0, + * and the value itself if it is NaN or +-0.0. + */ + public static double signum(double value) { + if (USE_JDK_MATH) { + return Math.signum(value); + } + if ((value == 0.0) || (value != value)) { + return value; + } + if (ANTI_SLOW_CASTS) { + return (double)(int)signFromBit(value); + } else { + return (double)signFromBit(value); + } + } + + /** + * @param value A float value. + * @return -1 if sign bit is 1, 1 if sign bit is 0. + */ + public static int signFromBit(float value) { + return ((Float.floatToRawIntBits(value)>>30)|1); + } + + /** + * @param value A double value. + * @return -1 if sign bit is 1, 1 if sign bit is 0. + */ + public static long signFromBit(double value) { + // Returning a long, to avoid useless cast into int. + return ((Double.doubleToRawLongBits(value)>>62)|1); + } + + /** + * A sign of NaN can be interpreted as positive or negative. + * + * @param magnitude A float value. + * @param sign A float value. + * @return A value with the magnitude of the first argument, and the sign + * of the second argument. + */ + public static float copySign(float magnitude, float sign) { + return Float.intBitsToFloat( + (Float.floatToRawIntBits(sign) & Integer.MIN_VALUE) + | (Float.floatToRawIntBits(magnitude) & Integer.MAX_VALUE)); + } + + /** + * A sign of NaN can be interpreted as positive or negative. + * + * @param magnitude A double value. + * @param sign A double value. + * @return A value with the magnitude of the first argument, and the sign + * of the second argument. + */ + public static double copySign(double magnitude, double sign) { + return Double.longBitsToDouble( + (Double.doubleToRawLongBits(sign) & Long.MIN_VALUE) + | (Double.doubleToRawLongBits(magnitude) & Long.MAX_VALUE)); + } + + /** + * The ULP (Unit in the Last Place) is the distance to the next value larger + * in magnitude. + * + * @param value A float value. + * @return The size of an ulp of the specified value, or Float.MIN_VALUE + * if it is +-0.0f, or +Infinity if it is +-Infinity, or NaN + * if it is NaN. + */ + public static float ulp(float value) { + if (USE_JDK_MATH) { + return Math.ulp(value); + } + /* + * Look-up table not really worth it in micro-benchmark, + * so should be worse with cache-misses. + */ + final int exponent = getExponent(value); + if (exponent >= (MIN_FLOAT_NORMAL_EXPONENT+23)) { + if (exponent == MAX_FLOAT_EXPONENT+1) { + // NaN or +-Infinity + return Math.abs(value); + } + // normal: returning 2^(exponent-23) + return Float.intBitsToFloat((exponent+(MAX_FLOAT_EXPONENT-23))<<23); + } else { + if (exponent == MIN_FLOAT_NORMAL_EXPONENT-1) { + // +-0.0f or subnormal + return Float.MIN_VALUE; + } + // subnormal result + return Float.intBitsToFloat(1<<(exponent-MIN_FLOAT_NORMAL_EXPONENT)); + } + } + + /** + * The ULP (Unit in the Last Place) is the distance to the next value larger + * in magnitude. + * + * @param value A double value. + * @return The size of an ulp of the specified value, or Double.MIN_VALUE + * if it is +-0.0, or +Infinity if it is +-Infinity, or NaN + * if it is NaN. + */ + public static double ulp(double value) { + if (USE_JDK_MATH) { + return Math.ulp(value); + } + /* + * Look-up table not really worth it in micro-benchmark, + * so should be worse with cache-misses. + */ + final int exponent = getExponent(value); + if (exponent >= (MIN_DOUBLE_NORMAL_EXPONENT+52)) { + if (exponent == MAX_DOUBLE_EXPONENT+1) { + // NaN or +-Infinity + return Math.abs(value); + } + // normal: returning 2^(exponent-52) + return Double.longBitsToDouble((exponent+(MAX_DOUBLE_EXPONENT-52L))<<52); + } else { + if (exponent == MIN_DOUBLE_NORMAL_EXPONENT-1) { + // +-0.0f or subnormal + return Double.MIN_VALUE; + } + // subnormal result + return Double.longBitsToDouble(1L<<(exponent-MIN_DOUBLE_NORMAL_EXPONENT)); + } + } + + /** + * If both arguments are +-0.0(f), (float)direction is returned. + * + * If both arguments are +Infinity or -Infinity, + * respectively +Infinity or -Infinity is returned. + * + * @param start A float value. + * @param direction A double value. + * @return The float adjacent to start towards direction, considering that + * +(-)Float.MIN_VALUE is adjacent to +(-)0.0f, and that + * +(-)Float.MAX_VALUE is adjacent to +(-)Infinity, + * or NaN if any argument is NaN. + */ + public static float nextAfter(float start, double direction) { + if (direction < start) { + // Going towards -Infinity. + if (start == 0.0f) { + // +-0.0f + return -Float.MIN_VALUE; + } + final int bits = Float.floatToRawIntBits(start); + return Float.intBitsToFloat(bits + ((bits > 0) ? -1 : 1)); + } else if (direction > start) { + // Going towards +Infinity. + // +0.0f to get rid of eventual -0.0f + final int bits = Float.floatToRawIntBits(start + 0.0f); + return Float.intBitsToFloat(bits + (bits >= 0 ? 1 : -1)); + } else if (start == direction) { + return (float)direction; + } else { + // Returning a NaN derived from the input NaN(s). + return start + (float)direction; + } + } + + /** + * If both arguments are +-0.0, direction is returned. + * + * If both arguments are +Infinity or -Infinity, + * respectively +Infinity or -Infinity is returned. + * + * @param start A double value. + * @param direction A double value. + * @return The double adjacent to start towards direction, considering that + * +(-)Double.MIN_VALUE is adjacent to +(-)0.0, and that + * +(-)Double.MAX_VALUE is adjacent to +(-)Infinity, + * or NaN if any argument is NaN. + */ + public static double nextAfter(double start, double direction) { + if (direction < start) { + // Going towards -Infinity. + if (start == 0.0) { + // +-0.0 + return -Double.MIN_VALUE; + } + final long bits = Double.doubleToRawLongBits(start); + return Double.longBitsToDouble(bits + ((bits > 0) ? -1 : 1)); + } else if (direction > start) { + // Going towards +Infinity. + // +0.0 to get rid of eventual -0.0 + final long bits = Double.doubleToRawLongBits(start + 0.0f); + return Double.longBitsToDouble(bits + (bits >= 0 ? 1 : -1)); + } else if (start == direction) { + return direction; + } else { + // Returning a NaN derived from the input NaN(s). + return start + direction; + } + } + + /** + * Semantically equivalent to nextAfter(start,Double.NEGATIVE_INFINITY). + */ + public static float nextDown(float start) { + if (start > Float.NEGATIVE_INFINITY) { + if (start == 0.0f) { + // +-0.0f + return -Float.MIN_VALUE; + } + final int bits = Float.floatToRawIntBits(start); + return Float.intBitsToFloat(bits + ((bits > 0) ? -1 : 1)); + } else if (start == Float.NEGATIVE_INFINITY) { + return Float.NEGATIVE_INFINITY; + } else { + // NaN + return start; + } + } + + /** + * Semantically equivalent to nextAfter(start,Double.NEGATIVE_INFINITY). + */ + public static double nextDown(double start) { + if (start > Double.NEGATIVE_INFINITY) { + if (start == 0.0) { + // +-0.0 + return -Double.MIN_VALUE; + } + final long bits = Double.doubleToRawLongBits(start); + return Double.longBitsToDouble(bits + ((bits > 0) ? -1 : 1)); + } else if (start == Double.NEGATIVE_INFINITY) { + return Double.NEGATIVE_INFINITY; + } else { + // NaN + return start; + } + } + + /** + * Semantically equivalent to nextAfter(start,Double.POSITIVE_INFINITY). + */ + public static float nextUp(float start) { + if (start < Float.POSITIVE_INFINITY) { + // +0.0f to get rid of eventual -0.0f + final int bits = Float.floatToRawIntBits(start + 0.0f); + return Float.intBitsToFloat(bits + (bits >= 0 ? 1 : -1)); + } else if (start == Float.POSITIVE_INFINITY) { + return Float.POSITIVE_INFINITY; + } else { + // NaN + return start; + } + } + + /** + * Semantically equivalent to nextAfter(start,Double.POSITIVE_INFINITY). + */ + public static double nextUp(double start) { + if (start < Double.POSITIVE_INFINITY) { + // +0.0 to get rid of eventual -0.0 + final long bits = Double.doubleToRawLongBits(start + 0.0); + return Double.longBitsToDouble(bits + (bits >= 0 ? 1 : -1)); + } else if (start == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } else { + // NaN + return start; + } + } + + /** + * Precision may be lost if the result is subnormal. + * + * @param value A float value. + * @param scaleFactor An int value. + * @return value * 2^scaleFactor, or a value equivalent to the specified + * one if it is NaN, +-Infinity or +-0.0f. + */ + public static float scalb(float value, int scaleFactor) { + // Large enough to imply overflow or underflow for + // a finite non-zero value. + final int MAX_SCALE = 2*MAX_FLOAT_EXPONENT+23+1; + + // Making sure scaling factor is in a reasonable range. + scaleFactor = Math.max(Math.min(scaleFactor, MAX_SCALE), -MAX_SCALE); + + return (float)(((double)value) * twoPowNormal(scaleFactor)); + } + + /** + * Precision may be lost if the result is subnormal. + * + * @param value A double value. + * @param scaleFactor An int value. + * @return value * 2^scaleFactor, or a value equivalent to the specified + * one if it is NaN, +-Infinity or +-0.0. + */ + public static double scalb(double value, int scaleFactor) { + if ((scaleFactor > -MAX_DOUBLE_EXPONENT) && (scaleFactor <= MAX_DOUBLE_EXPONENT)) { + // Quick case (as done in apache FastMath). + return value * twoPowNormal(scaleFactor); + } + + // Large enough to imply overflow or underflow for + // a finite non-zero value. + final int MAX_SCALE = 2*MAX_DOUBLE_EXPONENT+52+1; + + // Making sure scaling factor is in a reasonable range. + final int exponentAdjust; + final int scaleIncrement; + final double exponentDelta; + if (scaleFactor < 0) { + scaleFactor = Math.max(scaleFactor, -MAX_SCALE); + scaleIncrement = -512; + exponentDelta = TWO_POW_N512; + } else { + scaleFactor = Math.min(scaleFactor, MAX_SCALE); + scaleIncrement = 512; + exponentDelta = TWO_POW_512; + } + + // Calculating (scaleFactor % +-512), 512 = 2^9, using + // technique from "Hacker's Delight" section 10-2. + final int t = ((scaleFactor >> (9-1)) >>> (32-9)); + exponentAdjust = ((scaleFactor + t) & (512-1)) - t; + + value *= twoPowNormal(exponentAdjust); + scaleFactor -= exponentAdjust; + + while (scaleFactor != 0) { + value *= exponentDelta; + scaleFactor -= scaleIncrement; + } + + return value; + } + + /* + * Non-redefined Math public values and treatments. + */ + + public static float abs(float a) { + return Math.abs(a); + } + + public static double abs(double a) { + return Math.abs(a); + } + + public static float min(float a, float b) { + return Math.min(a,b); + } + + public static double min(double a, double b) { + return Math.min(a,b); + } + + public static float max(float a, float b) { + return Math.max(a,b); + } + + public static double max(double a, double b) { + return Math.max(a,b); + } + + public static double IEEEremainder(double f1, double f2) { + return Math.IEEEremainder(f1,f2); + } + + public static double random() { + return Math.random(); + } + + //-------------------------------------------------------------------------- + // PRIVATE METHODS + //-------------------------------------------------------------------------- + + /** + * Non-instantiable. + */ + private FastMath() { + } + + /* + * Remainders (accurate). + */ + + /** + * @param angle Angle in radians. + * @return Remainder of (angle % (2*PI)), in [-PI,PI]. + */ + private static double remainderTwoPi(double angle) { + if (USE_JDK_MATH) { + return jdkRemainderTwoPi(angle); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + if (angle <= (4*NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2)) { + double fn = (double)(int)(angle*TWOPI_INV+0.5); + angle = (angle - fn*TWOPI_HI) - fn*TWOPI_LO; + // Ensuring range. + // HI/LO can help a bit, even though we are always far from 0. + if (angle < -Math.PI) { + angle = (angle + TWOPI_HI) + TWOPI_LO; + } else if (angle > Math.PI) { + angle = (angle - TWOPI_HI) - TWOPI_LO; + } + return negateResult ? -angle : angle; + } else if (angle < Double.POSITIVE_INFINITY) { + angle = heavyRemainderTwoPi(angle); + return negateResult ? -angle : angle; + } else { // angle is +Infinity or NaN + return Double.NaN; + } + } + + /** + * @param angle Angle in radians. + * @return Remainder of (angle % PI), in [-PI/2,PI/2]. + */ + private static double remainderPi(double angle) { + if (USE_JDK_MATH) { + return jdkRemainderPi(angle); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + if (angle <= (2*NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2)) { + double fn = (double)(int)(angle*PI_INV+0.5); + angle = (angle - fn*PI_HI) - fn*PI_LO; + // Ensuring range. + // HI/LO can help a bit, even though we are always far from 0. + if (angle < -Math.PI/2) { + angle = (angle + PI_HI) + PI_LO; + } else if (angle > Math.PI/2) { + angle = (angle - PI_HI) - PI_LO; + } + return negateResult ? -angle : angle; + } else if (angle < Double.POSITIVE_INFINITY) { + angle = heavyRemainderPi(angle); + return negateResult ? -angle : angle; + } else { // angle is +Infinity or NaN + return Double.NaN; + } + } + + /** + * @param angle Angle in radians. + * @return Bits of double corresponding to remainder of (angle % (PI/2)), + * in [-PI/4,PI/4], with quadrant encoded in exponent bits. + */ + private static long remainderPiO2(double angle) { + if (USE_JDK_MATH) { + return jdkRemainderPiO2(angle, false); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + if (angle <= NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2) { + int n = (int)(angle*PIO2_INV+0.5); + double fn = (double)n; + angle = (angle - fn*PIO2_HI) - fn*PIO2_LO; + // Ensuring range. + // HI/LO can help a bit, even though we are always far from 0. + if (angle < -Math.PI/4) { + angle = (angle + PIO2_HI) + PIO2_LO; + n--; + } else if (angle > Math.PI/4) { + angle = (angle - PIO2_HI) - PIO2_LO; + n++; + } + if (negateResult) { + angle = -angle; + } + return encodeRemainderAndQuadrant(angle, n&3); + } else if (angle < Double.POSITIVE_INFINITY) { + return heavyRemainderPiO2(angle, negateResult); + } else { // angle is +Infinity or NaN + return encodeRemainderAndQuadrant(Double.NaN, 0); + } + } + + /* + * Remainders (fast). + */ + + /** + * Not accurate for large values. + * + * @param angle Angle in radians. + * @return Remainder of (angle % (2*PI)), in [-PI,PI]. + */ + private static double remainderTwoPiFast(double angle) { + if (USE_JDK_MATH) { + return jdkRemainderTwoPi(angle); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + // - We don't bother with values higher than (2*PI*(2^52)), + // since they are spaced by 2*PI or more from each other. + // - For large values, we don't use % because it might be very slow, + // and we split computation in two, because cast from double to int + // with large numbers might be very slow also. + if (angle <= TWO_POW_26*(2*Math.PI)) { + // ok + } else if (angle <= TWO_POW_52*(2*Math.PI)) { + // Computing remainder of angle modulo TWO_POW_26*(2*PI). + double fn = (double)(int)(angle*(TWOPI_INV/TWO_POW_26)+0.5); + angle = (angle - fn*(TWOPI_HI*TWO_POW_26)) - fn*(TWOPI_LO*TWO_POW_26); + // Here, angle is in [-TWO_POW_26*PI,TWO_POW_26*PI], or so. + if (angle < 0.0) { + angle = -angle; + negateResult = !negateResult; + } + } else if (angle < Double.POSITIVE_INFINITY) { + return 0.0; + } else { // angle is +Infinity or NaN + return Double.NaN; + } + + // Computing remainder of angle modulo 2*PI. + double fn = (double)(int)(angle*TWOPI_INV+0.5); + angle = (angle - fn*TWOPI_HI) - fn*TWOPI_LO; + + // Ensuring range. + // HI/LO can help a bit, even though we are always far from 0. + if (angle < -Math.PI) { + angle = (angle + TWOPI_HI) + TWOPI_LO; + } else if (angle > Math.PI) { + angle = (angle - TWOPI_HI) - TWOPI_LO; + } + return negateResult ? -angle : angle; + } + + /** + * Not accurate for large values. + * + * @param angle Angle in radians. + * @return Remainder of (angle % PI), in [-PI/2,PI/2]. + */ + private static double remainderPiFast(double angle) { + if (USE_JDK_MATH) { + return jdkRemainderPi(angle); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + // - We don't bother with values higher than (PI*(2^52)), + // since they are spaced by PI or more from each other. + // - For large values, we don't use % because it might be very slow, + // and we split computation in two, because cast from double to int + // with large numbers might be very slow also. + if (angle <= TWO_POW_26*Math.PI) { + // ok + } else if (angle <= TWO_POW_52*Math.PI) { + // Computing remainder of angle modulo TWO_POW_26*PI. + double fn = (double)(int)(angle*(PI_INV/TWO_POW_26)+0.5); + angle = (angle - fn*(PI_HI*TWO_POW_26)) - fn*(PI_LO*TWO_POW_26); + // Here, angle is in [-TWO_POW_26*PI/2,TWO_POW_26*PI/2], or so. + if (angle < 0.0) { + angle = -angle; + negateResult = !negateResult; + } + } else if (angle < Double.POSITIVE_INFINITY) { + return 0.0; + } else { // angle is +Infinity or NaN + return Double.NaN; + } + + // Computing remainder of angle modulo PI. + double fn = (double)(int)(angle*PI_INV+0.5); + angle = (angle - fn*PI_HI) - fn*PI_LO; + + // Ensuring range. + // HI/LO can help a bit, even though we are always far from 0. + if (angle < -Math.PI/2) { + angle = (angle + PI_HI) + PI_LO; + } else if (angle > Math.PI/2) { + angle = (angle - PI_HI) - PI_LO; + } + return negateResult ? -angle : angle; + } +} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/IntWrapper.java b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/IntWrapper.java new file mode 100644 index 000000000..812e5a22d --- /dev/null +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/IntWrapper.java @@ -0,0 +1,13 @@ +/* + * 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.jafama; + +public class IntWrapper { + public int value; + @Override + public String toString() { + return Integer.toString(this.value); + } +} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt new file mode 100644 index 000000000..2b6cc3a5a --- /dev/null +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt @@ -0,0 +1,102 @@ +package space.kscience.kmath.jafama + +import space.kscience.kmath.operations.* + +/** + * Advanced Number-like semifield that implements basic operations. + */ +public interface ExtendedFieldOperations : + FieldOperations, + TrigonometricOperations, + PowerOperations, + ExponentialOperations { + public override fun tan(arg: T): T = sin(arg) / cos(arg) + public override fun tanh(arg: T): T = sinh(arg) / cosh(arg) + + public override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) { + TrigonometricOperations.COS_OPERATION -> ::cos + TrigonometricOperations.SIN_OPERATION -> ::sin + TrigonometricOperations.TAN_OPERATION -> ::tan + TrigonometricOperations.ACOS_OPERATION -> ::acos + TrigonometricOperations.ASIN_OPERATION -> ::asin + TrigonometricOperations.ATAN_OPERATION -> ::atan + PowerOperations.SQRT_OPERATION -> ::sqrt + ExponentialOperations.EXP_OPERATION -> ::exp + ExponentialOperations.LN_OPERATION -> ::ln + ExponentialOperations.COSH_OPERATION -> ::cosh + ExponentialOperations.SINH_OPERATION -> ::sinh + ExponentialOperations.TANH_OPERATION -> ::tanh + ExponentialOperations.ACOSH_OPERATION -> ::acosh + ExponentialOperations.ASINH_OPERATION -> ::asinh + ExponentialOperations.ATANH_OPERATION -> ::atanh + else -> super.unaryOperationFunction(operation) + } +} + +/** + * Advanced Number-like field that implements basic operations. + */ +public interface ExtendedField : ExtendedFieldOperations, Field, NumericAlgebra, ScaleOperations { + public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2.0 + public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2.0 + public override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg)) + public override fun asinh(arg: T): T = ln(sqrt(arg * arg + one) + arg) + public override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one))) + public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2.0 + + public override fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T = + when (operation) { + PowerOperations.POW_OPERATION -> ::power + else -> super.rightSideNumberOperationFunction(operation) + } +} + +/** + * A field for [Double] without boxing. Does not produce appropriate field element. + */ +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +public object DoubleField : ExtendedField, Norm, ScaleOperations { + public override inline val zero: Double get() = 0.0 + public override inline val one: Double get() = 1.0 + + public override fun number(value: Number): Double = value.toDouble() + + public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double = + when (operation) { + PowerOperations.POW_OPERATION -> ::power + else -> super.binaryOperationFunction(operation) + } + + public override inline fun add(a: Double, b: Double): Double = a + b + + public override inline fun multiply(a: Double, b: Double): Double = a * b + public override inline fun divide(a: Double, b: Double): Double = a / b + + public override fun scale(a: Double, value: Double): Double = a * value + + public override inline fun sin(arg: Double): Double = FastMath.sin(arg) + public override inline fun cos(arg: Double): Double = FastMath.cos(arg) + public override inline fun tan(arg: Double): Double = FastMath.tan(arg) + public override inline fun acos(arg: Double): Double = FastMath.acos(arg) + public override inline fun asin(arg: Double): Double = FastMath.asin(arg) + public override inline fun atan(arg: Double): Double = FastMath.atan(arg) + + public override inline fun sinh(arg: Double): Double = FastMath.sinh(arg) + public override inline fun cosh(arg: Double): Double = FastMath.cosh(arg) + public override inline fun tanh(arg: Double): Double = FastMath.tanh(arg) + public override inline fun asinh(arg: Double): Double = FastMath.asinh(arg) + public override inline fun acosh(arg: Double): Double = FastMath.acosh(arg) + public override inline fun atanh(arg: Double): Double = FastMath.atanh(arg) + + public override inline fun power(arg: Double, pow: Number): Double = FastMath.pow(arg, pow.toDouble()) + public override inline fun exp(arg: Double): Double = FastMath.exp(arg) + public override inline fun ln(arg: Double): Double = FastMath.log(arg) + + public override inline fun norm(arg: Double): Double = FastMath.abs(arg) + + public override inline fun Double.unaryMinus(): Double = -this + public override inline fun Double.plus(b: Double): Double = this + b + public override inline fun Double.minus(b: Double): Double = this - b + public override inline fun Double.times(b: Double): Double = this * b + public override inline fun Double.div(b: Double): Double = this / b +} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/NumbersUtils.java b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/NumbersUtils.java new file mode 100644 index 000000000..6fdd9dea5 --- /dev/null +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/NumbersUtils.java @@ -0,0 +1,2647 @@ +/* + * 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.jafama; + +/** + * Class containing various basic utility methods to deal with numbers. + * This class is meant to be light (no big look-up tables or such). + * + * Check methods return boolean if success, + * for it allows to use them in assertions. + * + * toString methods use capital letters, unlike JDK's toStrings, for it is more + * readable (especially, "l" and "1" can easily be confused with one another). + * + * Some methods have an int version additionally to the long version, + * even though long version could be used instead, for performance reasons, + * either for the methods themselves (if they do computations with ints + * instead of longs), or to be used in an int use case (like methods + * checking whether or not a signed int can fit in such number of bits). + */ +public final class NumbersUtils { + + //-------------------------------------------------------------------------- + // MEMBERS + //-------------------------------------------------------------------------- + + /** + * Double.MIN_NORMAL since Java 6. + */ + public static final double DOUBLE_MIN_NORMAL = Double.longBitsToDouble(0x0010000000000000L); // 2.2250738585072014E-308 + + /** + * Float.MIN_NORMAL since Java 6. + */ + public static final float FLOAT_MIN_NORMAL = Float.intBitsToFloat(0x00800000); // 1.17549435E-38f + + private static final int MIN_DOUBLE_EXPONENT = -1074; + private static final int MAX_DOUBLE_EXPONENT = 1023; + + /** + * All possible upper case chars for representing a number as a String. + */ + private final static char[] CHAR_BY_DIGIT; + static { + final char minDecimal = '0'; + final char maxDecimal = '9'; + final int n1 = maxDecimal - minDecimal + 1; + final char minLetter = 'A'; + final char maxLetter = 'Z'; + final int n2 = maxLetter - minLetter + 1; + CHAR_BY_DIGIT = new char[n1+n2]; + int i=0; + for (char c=minDecimal;c<=maxDecimal;c++) { + CHAR_BY_DIGIT[i++] = c; + } + for (char c=minLetter;c<=maxLetter;c++) { + CHAR_BY_DIGIT[i++] = c; + } + } + + /** + * For power-of-two radixes only. + */ + private static final int[] DIV_SHIFT_BY_RADIX; + static { + DIV_SHIFT_BY_RADIX = new int[32+1]; + int shift=1; + for (int radix=2;radix<=32;radix*=2) { + DIV_SHIFT_BY_RADIX[radix] = shift++; + } + } + + private final static int[] MAX_NBR_OF_NEG_INT_DIGITS_BY_RADIX = new int[Character.MAX_RADIX+1]; + private final static int[] MAX_NBR_OF_NEG_LONG_DIGITS_BY_RADIX = new int[Character.MAX_RADIX+1]; + static { + for (int radix=Character.MIN_RADIX;radix<=Character.MAX_RADIX;radix++) { + /* + * Brutal but works. + * -1 for the sign. + */ + MAX_NBR_OF_NEG_INT_DIGITS_BY_RADIX[radix] = Integer.toString(Integer.MIN_VALUE, radix).length()-1; + MAX_NBR_OF_NEG_LONG_DIGITS_BY_RADIX[radix] = Long.toString(Long.MIN_VALUE, radix).length()-1; + } + } + + static final double NO_CSN_MIN_BOUND_INCL = 1e-3; + static final double NO_CSN_MAX_BOUND_EXCL = 1e7; + + private static final double PIO2_HI = Double.longBitsToDouble(0x3FF921FB54400000L); // 1.57079632673412561417e+00 first 33 bits of pi/2 + private static final double PIO2_LO = Double.longBitsToDouble(0x3DD0B4611A626331L); // 6.07710050650619224932e-11 pi/2 - PIO2_HI + private static final double PI_HI = 2*PIO2_HI; + private static final double PI_LO = 2*PIO2_LO; + private static final double TWOPI_HI = 4*PIO2_HI; + private static final double TWOPI_LO = 4*PIO2_LO; + + //-------------------------------------------------------------------------- + // PUBLIC METHODS + //-------------------------------------------------------------------------- + + /** + * @return True if the specified values are equal or both NaN, false otherwise. + */ + public static boolean equal(float a, float b) { + // Only does one test if a == b. + return (a == b) ? true : ((a != a) && (b != b)); + } + + /** + * @return True if the specified values are equal or both NaN, false otherwise. + */ + public static boolean equal(double a, double b) { + // Only does one test if a == b. + return (a == b) ? true : ((a != a) && (b != b)); + } + + /** + * @return True if the specified value is a mathematical integer, + * false otherwise (which includes NaN and +-Infinity). + */ + public static boolean isMathematicalInteger(float value) { + // Doing magnitude test first, for cast + // might be very slow for huge values. + // It also helps be faster for huge values, + // for which the test with cast always fail. + value = Math.abs(value); + return ((value >= (float)(1<<23) + && (value != Float.POSITIVE_INFINITY))) + || (value == (float)(int)value); + } + + /** + * @return True if the specified value is a mathematical integer, + * false otherwise (which includes NaN and +-Infinity). + */ + public static boolean isMathematicalInteger(double value) { + // Doing magnitude test first, for cast + // might be very slow for huge values. + // It also helps be faster for huge values, + // for which the test with cast always fail. + value = Math.abs(value); + return ((value >= (double)(1L<<52)) + && (value != Double.POSITIVE_INFINITY)) + || (value == (double)(long)value); + } + + /** + * @param value A float value. + * @return True if the specified value is equidistant from two adjacent + * mathematical integers, false otherwise (which includes NaN + * and +-Infinity). + */ + public static boolean isEquidistant(float value) { + if (false) { + // Also works, but slower. + final int bits = Float.floatToRawIntBits(value); + final int exponent = ((bits>>23)&0xFF)-127; + final int nbrOfPostCommaBits = 23 - exponent; + if ((nbrOfPostCommaBits <= 0) || (nbrOfPostCommaBits >= 25)) { + // No mantissa bit after comma, or all mantissa bits + // (including implicit 1) are at least one bit away from it. + //System.out.println("can't be"); + return false; + } + final int mantissa = 0x00800000|(bits&0x007FFFFF); + final int postCommaMask = ~((-1)<>52))&0x7FF)-1023; + final int nbrOfPostCommaBits = 52 - exponent; + if ((nbrOfPostCommaBits <= 0) || (nbrOfPostCommaBits >= 54)) { + // No mantissa bit after comma, or all mantissa bits + // (including implicit 1) are at least one bit away from it. + return false; + } + final long mantissa = 0x0010000000000000L|(bits&0x000FFFFFFFFFFFFFL); + final long postCommaMask = ~((-1L)< value is NaN or +-Infinity + return !(value-value == 0.0f); + } + + /** + * @param value A double value. + * @return True if the specified value is NaN or +-Infinity, false otherwise. + */ + public static boolean isNaNOrInfinite(double value) { + // value-value is not equal to 0.0 (and is NaN) <-> value is NaN or +-Infinity + return !(value-value == 0.0); + } + + /** + * @param value A float value. + * @return -1 if sign bit is 1, 1 if sign bit is 0. + */ + public static int signFromBit(float value) { + return ((Float.floatToRawIntBits(value)>>30)|1); + } + + /** + * @param value A double value. + * @return -1 if sign bit is 1, 1 if sign bit is 0. + */ + public static long signFromBit(double value) { + // Returning a long, to avoid useless cast into int. + return ((Double.doubleToRawLongBits(value)>>62)|1); + } + + /* + * min/max ranges + */ + + /** + * @return True if the specified value is in the specified range (inclusive), false otherwise. + */ + public static boolean isInRange(int min, int max, int a) { + return (min <= a) && (a <= max); + } + + /** + * @return True if the specified value is in the specified range (inclusive), false otherwise. + */ + public static boolean isInRange(long min, long max, long a) { + return (min <= a) && (a <= max); + } + + /** + * Returns false if any value is NaN. + * + * @return True if the specified value is in the specified range (inclusive), false otherwise. + */ + public static boolean isInRange(float min, float max, float a) { + return (min <= a) && (a <= max); + } + + /** + * Returns false if any value is NaN. + * + * @return True if the specified value is in the specified range (inclusive), false otherwise. + */ + public static boolean isInRange(double min, double max, double a) { + return (min <= a) && (a <= max); + } + + /* + * + */ + + /** + * @return True if does not throw. + * @throws IllegalArgumentException if the specified value is not in the specified range (inclusive). + */ + public static boolean checkIsInRange(int min, int max, int a) { + if (!isInRange(min, max, a)) { + throw new IllegalArgumentException(a+" not in ["+min+","+max+"]"); + } + return true; + } + + /** + * @return True if does not throw. + * @throws IllegalArgumentException if the specified value is not in the specified range (inclusive). + */ + public static boolean checkIsInRange(long min, long max, long a) { + if (!isInRange(min, max, a)) { + throw new IllegalArgumentException(a+" not in ["+min+","+max+"]"); + } + return true; + } + + /** + * @return True if does not throw. + * @throws IllegalArgumentException if the specified value is not in the specified range (inclusive) + * or any parameter is NaN. + */ + public static boolean checkIsInRange(float min, float max, float a) { + if (!isInRange(min, max, a)) { + throw new IllegalArgumentException(a+" not in ["+min+","+max+"]"); + } + return true; + } + + /** + * @return True if does not throw. + * @throws IllegalArgumentException if the specified value is not in the specified range (inclusive) + * or any parameter is NaN. + */ + public static boolean checkIsInRange(double min, double max, double a) { + if (!isInRange(min, max, a)) { + throw new IllegalArgumentException(a+" not in ["+min+","+max+"]"); + } + return true; + } + + /* + * + */ + + /** + * @param min A value. + * @param max A value. + * @param a A value. + * @return min if a <= min, else max if a >= max, else a. + */ + public static int toRange(int min, int max, int a) { + if (a <= min) { + return min; + } else if (a >= max) { + return max; + } else { + return a; + } + } + + /** + * @param min A value. + * @param max A value. + * @param a A value. + * @return min if a <= min, else max if a >= max, else a. + */ + public static long toRange(long min, long max, long a) { + if (a <= min) { + return min; + } else if (a >= max) { + return max; + } else { + return a; + } + } + + /** + * @param min A value. + * @param max A value. + * @param a A value. + * @return min if a <= min, else max if a >= max, else a. + */ + public static float toRange(float min, float max, float a) { + if (a <= min) { + return min; + } else if (a >= max) { + return max; + } else { + return a; + } + } + + /** + * @param min A value. + * @param max A value. + * @param a A value. + * @return min if a <= min, else max if a >= max, else a. + */ + public static double toRange(double min, double max, double a) { + if (a <= min) { + return min; + } else if (a >= max) { + return max; + } else { + return a; + } + } + + /* + * bitwise ranges + */ + + /** + * @param bitSize A number of bits, in [1,32]. + * @return True if the specified value fits as a signed integer + * over the specified number of bits, false otherwise. + * @throws IllegalArgumentException if the specified number of bits is not in [1,32]. + */ + public static boolean isInRangeSigned(int a, int bitSize) { + checkBitSizeForSignedInt(bitSize); + return (minSignedIntForBitSize_noCheck(bitSize) <= a) && (a <= maxSignedIntForBitSize_noCheck(bitSize)); + } + + /** + * @param bitSize A number of bits, in [1,64]. + * @return True if the specified value fits as a signed integer + * over the specified number of bits, false otherwise. + * @throws IllegalArgumentException if the specified number of bits is not in [1,64]. + */ + public static boolean isInRangeSigned(long a, int bitSize) { + checkBitSizeForSignedLong(bitSize); + return (minSignedLongForBitSize_noCheck(bitSize) <= a) && (a <= maxSignedLongForBitSize_noCheck(bitSize)); + } + + /** + * @param bitSize A number of bits, in [1,31]. + * @return True if the specified value fits as an unsigned integer + * over the specified number of bits, false otherwise. + * @throws IllegalArgumentException if the specified number of bits is not in [1,31]. + */ + public static boolean isInRangeUnsigned(int a, int bitSize) { + return isInRange(0, maxUnsignedIntForBitSize(bitSize), a); + } + + /** + * @param bitSize A number of bits, in [1,63]. + * @return True if the specified value fits as an unsigned integer + * over the specified number of bits, false otherwise. + * @throws IllegalArgumentException if the specified number of bits is not in [1,63]. + */ + public static boolean isInRangeUnsigned(long a, int bitSize) { + return isInRange(0, maxUnsignedLongForBitSize(bitSize), a); + } + + /* + * + */ + + /** + * @param bitSize A number of bits, in [1,32]. + * @return True if does not throw. + * @throws IllegalArgumentException if the specified value does not fit + * as a signed integer over the specified number of bits. + */ + public static boolean checkIsInRangeSigned(int a, int bitSize) { + if (!isInRangeSigned(a, bitSize)) { + throw new IllegalArgumentException(a+" does not fit as a signed value over "+bitSize+" bits"); + } + return true; + } + + /** + * @param bitSize A number of bits, in [1,64]. + * @return True if does not throw. + * @throws IllegalArgumentException if the specified value does not fit + * as a signed integer over the specified number of bits. + */ + public static boolean checkIsInRangeSigned(long a, int bitSize) { + if (!isInRangeSigned(a, bitSize)) { + throw new IllegalArgumentException(a+" does not fit as a signed value over "+bitSize+" bits"); + } + return true; + } + + /** + * @param bitSize A number of bits, in [1,31]. + * @return True if does not throw. + * @throws IllegalArgumentException if the specified value does not fit + * as an unsigned integer over the specified number of bits. + */ + public static boolean checkIsInRangeUnsigned(int a, int bitSize) { + if (!isInRangeUnsigned(a, bitSize)) { + throw new IllegalArgumentException(a+" does not fit as an unsigned value over "+bitSize+" bits"); + } + return true; + } + + /** + * @param bitSize A number of bits, in [1,63]. + * @return True if does not throw. + * @throws IllegalArgumentException if the specified value does not fit + * as an unsigned integer over the specified number of bits. + */ + public static boolean checkIsInRangeUnsigned(long a, int bitSize) { + if (!isInRangeUnsigned(a, bitSize)) { + throw new IllegalArgumentException(a+" does not fit as an unsigned value over "+bitSize+" bits"); + } + return true; + } + + /* + * masks (int) + */ + + /** + * @param bitSize A number of bits, in [0,32]. + * @return Mask with the specified number of left bits set with 0, + * and other bits set with 1. + */ + public static int intMaskMSBits0(int bitSize) { + checkIsInRange(0, 32, bitSize); + // Shifting in two times, for >>> doesn't work for full bit size (<< as well). + final int halfish = (bitSize>>1); + return ((-1)>>>halfish)>>>(bitSize-halfish); + } + + /** + * @param bitSize A number of bits, in [0,32]. + * @return Mask with the specified number of left bits set with 1, + * and other bits set with 0. + */ + public static int intMaskMSBits1(int bitSize) { + return ~intMaskMSBits0(bitSize); + } + + /** + * @param bitSize A number of bits, in [0,32]. + * @return Mask with the specified number of right bits set with 0, + * and other bits set with 1. + */ + public static int intMaskLSBits0(int bitSize) { + return ~intMaskMSBits0(32-bitSize); + } + + /** + * @param bitSize A number of bits, in [0,32]. + * @return Mask with the specified number of right bits set with 1, + * and other bits set with 0. + */ + public static int intMaskLSBits1(int bitSize) { + return intMaskMSBits0(32-bitSize); + } + + /* + * masks (long) + */ + + /** + * @param bitSize A number of bits, in [0,64]. + * @return Mask with the specified number of left bits set with 0, + * and other bits set with 1. + */ + public static long longMaskMSBits0(int bitSize) { + checkIsInRange(0, 64, bitSize); + // Shifting in two times, for >>> doesn't work for full bit size (<< as well). + final int halfish = (bitSize>>1); + return ((-1L)>>>halfish)>>>(bitSize-halfish); + } + + /** + * @param bitSize A number of bits, in [0,64]. + * @return Mask with the specified number of left bits set with 1, + * and other bits set with 0. + */ + public static long longMaskMSBits1(int bitSize) { + return ~longMaskMSBits0(bitSize); + } + + /** + * @param bitSize A number of bits, in [0,64]. + * @return Mask with the specified number of right bits set with 0, + * and other bits set with 1. + */ + public static long longMaskLSBits0(int bitSize) { + return ~longMaskMSBits0(64-bitSize); + } + + /** + * @param bitSize A number of bits, in [0,64]. + * @return Mask with the specified number of right bits set with 1, + * and other bits set with 0. + */ + public static long longMaskLSBits1(int bitSize) { + return longMaskMSBits0(64-bitSize); + } + + /* + * signed/unsigned + */ + + /** + * @return Unsigned value corresponding to bits of the specified byte. + */ + public static short byteAsUnsigned(byte value) { + return (short)(((short)value) & 0xFF); + } + + /** + * @return Unsigned value corresponding to bits of the specified short. + */ + public static int shortAsUnsigned(short value) { + return ((int)value) & 0xFFFF; + } + + /** + * @return Unsigned value corresponding to bits of the specified int. + */ + public static long intAsUnsigned(int value) { + return ((long)value) & 0xFFFFFFFF; + } + + /* + * bitwise ranges + */ + + /** + * @return True if a signed int value can be read over the specified number of bits, + * i.e. if it is in [1,32], false otherwise. + */ + public static boolean isValidBitSizeForSignedInt(int bitSize) { + return (bitSize > 0) && (bitSize <= 32); + } + + /** + * @return True if a signed long value can be read over the specified number of bits, + * i.e. if it is in [1,64], false otherwise. + */ + public static boolean isValidBitSizeForSignedLong(int bitSize) { + return (bitSize > 0) && (bitSize <= 64); + } + + /** + * @return True if an unsigned int value can be read over the specified number of bits, + * i.e. if it is in [1,31], false otherwise. + */ + public static boolean isValidBitSizeForUnsignedInt(int bitSize) { + return (bitSize > 0) && (bitSize < 32); + } + + /** + * @return True if an unsigned long value can be read over the specified number of bits, + * i.e. if it is in [1,63], false otherwise. + */ + public static boolean isValidBitSizeForUnsignedLong(int bitSize) { + return (bitSize > 0) && (bitSize < 64); + } + + /* + * + */ + + /** + * @return True if does not throw. + * @throws IllegalArgumentException if a signed int value can't be read over the + * specified number of bits, i.e. if it is not in [1,32]. + */ + public static boolean checkBitSizeForSignedInt(int bitSize) { + if (!isValidBitSizeForSignedInt(bitSize)) { + throw new IllegalArgumentException("bit size ["+bitSize+"] must be in [1,32] for signed int values"); + } + return true; + } + + /** + * @return True if does not throw. + * @throws IllegalArgumentException if a signed long value can't be read over the + * specified number of bits, i.e. if it is not in [1,64]. + */ + public static boolean checkBitSizeForSignedLong(int bitSize) { + if (!isValidBitSizeForSignedLong(bitSize)) { + throw new IllegalArgumentException("bit size ["+bitSize+"] must be in [1,64] for signed long values"); + } + return true; + } + + /** + * @return True if does not throw. + * @throws IllegalArgumentException if an unsigned int value can't be read over the + * specified number of bits, i.e. if it is not in [1,31]. + */ + public static boolean checkBitSizeForUnsignedInt(int bitSize) { + if (!isValidBitSizeForUnsignedInt(bitSize)) { + throw new IllegalArgumentException("bit size ["+bitSize+"] must be in [1,31] for unsigned int values"); + } + return true; + } + + /** + * @return True if does not throw. + * @throws IllegalArgumentException if an unsigned long value can't be read over the + * specified number of bits, i.e. if it is not in [1,63]. + */ + public static boolean checkBitSizeForUnsignedLong(int bitSize) { + if (!isValidBitSizeForUnsignedLong(bitSize)) { + throw new IllegalArgumentException("bit size ["+bitSize+"] must be in [1,63] for unsigned long values"); + } + return true; + } + + /* + * + */ + + /** + * @param bitSize A number of bits in [1,32]. + * @return The min signed int value that can be stored over the specified number of bits. + * @throws IllegalArgumentException if the specified number of bits is out of range. + */ + public static int minSignedIntForBitSize(int bitSize) { + checkBitSizeForSignedInt(bitSize); + return minSignedIntForBitSize_noCheck(bitSize); + } + + /** + * @param bitSize A number of bits in [1,64]. + * @return The min signed long value that can be stored over the specified number of bits. + * @throws IllegalArgumentException if the specified number of bits is out of range. + */ + public static long minSignedLongForBitSize(int bitSize) { + checkBitSizeForSignedLong(bitSize); + return minSignedLongForBitSize_noCheck(bitSize); + } + + /** + * @param bitSize A number of bits in [1,32]. + * @return The max signed int value that can be stored over the specified number of bits. + * @throws IllegalArgumentException if the specified number of bits is out of range. + */ + public static int maxSignedIntForBitSize(int bitSize) { + checkBitSizeForSignedInt(bitSize); + return maxSignedIntForBitSize_noCheck(bitSize); + } + + /** + * @param bitSize A number of bits in [1,64]. + * @return The max signed long value that can be stored over the specified number of bits. + * @throws IllegalArgumentException if the specified number of bits is out of range. + */ + public static long maxSignedLongForBitSize(int bitSize) { + checkBitSizeForSignedLong(bitSize); + return maxSignedLongForBitSize_noCheck(bitSize); + } + + /** + * @param bitSize A number of bits in [1,31]. + * @return The max unsigned int value that can be stored over the specified number of bits. + * @throws IllegalArgumentException if the specified number of bits is out of range. + */ + public static int maxUnsignedIntForBitSize(int bitSize) { + checkBitSizeForUnsignedInt(bitSize); + // i.e. (1<>(31-bitSize)); + } + + /** + * @param bitSize A number of bits in [1,63]. + * @return The max unsigned long value that can be stored over the specified number of bits. + * @throws IllegalArgumentException if the specified number of bits is out of range. + */ + public static long maxUnsignedLongForBitSize(int bitSize) { + checkBitSizeForUnsignedLong(bitSize); + // i.e. (1L<>(63-bitSize)); + } + + /* + * + */ + + /** + * @return The number of bits required to store the specified value as a signed integer, + * i.e. a result in [1,32]. + */ + public static int bitSizeForSignedValue(int value) { + if (value > 0) { + return 33-Integer.numberOfLeadingZeros(value); + } else if (value == 0) { + return 1; + } else { + // Works for Integer.MIN_VALUE as well. + return 33-Integer.numberOfLeadingZeros(-value-1); + } + } + + /** + * @return The number of bits required to store the specified value as a signed integer, + * i.e. a result in [1,64]. + */ + public static int bitSizeForSignedValue(long value) { + if (value > 0) { + return 65-Long.numberOfLeadingZeros(value); + } else if (value == 0) { + return 1; + } else { + // Works for Long.MIN_VALUE as well. + return 65-Long.numberOfLeadingZeros(-value-1); + } + } + + /** + * @param value An integer value in [0,Integer.MAX_VALUE]. + * @return The number of bits required to store the specified value as an unsigned integer, + * i.e. a result in [1,31]. + * @throws IllegalArgumentException if the specified value is < 0. + */ + public static int bitSizeForUnsignedValue(int value) { + if (value > 0) { + return 32-Integer.numberOfLeadingZeros(value); + } else { + if (value == 0) { + return 1; + } else { + throw new IllegalArgumentException("unsigned value ["+value+"] must be >= 0"); + } + } + } + + /** + * @param value An integer value in [0,Long.MAX_VALUE]. + * @return The number of bits required to store the specified value as an unsigned integer, + * i.e. a result in [1,63]. + * @throws IllegalArgumentException if the specified value is < 0. + */ + public static int bitSizeForUnsignedValue(long value) { + if (value > 0) { + return 64-Long.numberOfLeadingZeros(value); + } else { + if (value == 0) { + return 1; + } else { + throw new IllegalArgumentException("unsigned value ["+value+"] must be >= 0"); + } + } + } + + /* + * integer functions + */ + + /** + * @return 1 if the specified value is > 0, 0 if it is 0, -1 otherwise. + */ + public static int signum(int a) { + return (a < 0) ? -1 : ((a == 0) ? 0 : 1); + } + + /** + * @return 1 if the specified value is > 0, 0 if it is 0, -1 otherwise. + */ + public static int signum(long a) { + return (a < 0) ? -1 : ((a == 0) ? 0 : 1); + } + + /** + * @return True if the specified value is even, false otherwise. + */ + public static boolean isEven(int a) { + return ((a&1) == 0); + } + + /** + * @return True if the specified value is even, false otherwise. + */ + public static boolean isEven(long a) { + // faster to work on ints + return isEven((int)a); + } + + /** + * @return True if the specified value is odd, false otherwise. + */ + public static boolean isOdd(int a) { + return ((a&1) != 0); + } + + /** + * @return True if the specified value is odd, false otherwise. + */ + public static boolean isOdd(long a) { + // faster to work on ints + return isOdd((int)a); + } + + /** + * @return True if the specified values are both even or both odd, false otherwise. + */ + public static boolean haveSameEvenness(int a, int b) { + return (((a^b)&1) == 0); + } + + /** + * @return True if the specified values are both even or both odd, false otherwise. + */ + public static boolean haveSameEvenness(long a, long b) { + // faster to work on ints + return haveSameEvenness((int)a, (int)b); + } + + /** + * @return True if the specified values are both >= 0 or both < 0, false otherwise. + */ + public static boolean haveSameSign(int a, int b) { + return ((a^b) >= 0); + } + + /** + * @return True if the specified values are both >= 0 or both < 0, false otherwise. + */ + public static boolean haveSameSign(long a, long b) { + return ((a^b) >= 0); + } + + /** + * @return True if the specified value is a power of two, + * i.e. a value of the form 2^k, with k >= 0. + */ + public static boolean isPowerOfTwo(int a) { + if (a <= 0) { + return false; + } + if (false) { + // also works + return (a & -a) == a; + } + return (a & (a-1)) == 0; + } + + /** + * @return True if the specified value is a power of two, + * i.e. a value of the form 2^k, with k >= 0. + */ + public static boolean isPowerOfTwo(long a) { + if (a <= 0) { + return false; + } + if (false) { + // also works + return (a & -a) == a; + } + return (a & (a-1)) == 0; + } + + /** + * @return True if the specified value is a signed power of two, + * i.e. a value of the form +-2^k, with k >= 0. + */ + public static boolean isSignedPowerOfTwo(int a) { + if (a > 0) { + return (a & (a-1)) == 0; + } else { + if (a == -a) { + // a is 0 or Integer.MIN_VALUE + return (a != 0); + } + return ((-a) & (-a-1)) == 0; + } + } + + /** + * @return True if the specified value is a signed power of two, + * i.e. a value of the form +-2^k, with k >= 0. + */ + public static boolean isSignedPowerOfTwo(long a) { + if (a > 0) { + return (a & (a-1)) == 0; + } else { + if (a == -a) { + // a is 0 or Long.MIN_VALUE + return (a != 0); + } + return ((-a) & (-a-1)) == 0; + } + } + + /** + * @param a A value in [1,Integer.MAX_VALUE]. + * @return The highest power of two <= a. + */ + public static int floorPowerOfTwo(int a) { + if (a <= 0) { + throw new IllegalArgumentException("a ["+a+"] must be > 0"); + } + return Integer.highestOneBit(a); + } + + /** + * @param a A value in [1,Long.MAX_VALUE]. + * @return The highest power of two <= a. + */ + public static long floorPowerOfTwo(long a) { + if (a <= 0) { + throw new IllegalArgumentException("a ["+a+"] must be > 0"); + } + // Faster than copying int method + // (less computations on long). + return 1L << (63 - Long.numberOfLeadingZeros(a)); + } + + /** + * @param a A value in [0,2^30]. + * @return The lowest power of two >= a. + */ + public static int ceilingPowerOfTwo(int a) { + checkIsInRange(0, (1<<30), a); + return (a >= 2) ? Integer.highestOneBit((a-1)<<1) : 1; + } + + /** + * @param a A value in [0,2^62]. + * @return The lowest power of two >= a. + */ + public static long ceilingPowerOfTwo(long a) { + checkIsInRange(0L, (1L<<62), a); + // Faster than copying int method + // (less computations on long). + return 1L << (64 - Long.numberOfLeadingZeros(a - 1)); + } + + /** + * @return Mean without overflow, rounded to the lowest value (i.e. mathematical floor((a+b)/2), using floating point division). + */ + public static int meanLow(int a, int b) { + return (a & b) + ((a ^ b) >> 1); + } + + /** + * @return Mean without overflow, rounded to the lowest value (i.e. mathematical floor((a+b)/2), using floating point division). + */ + public static long meanLow(long a, long b) { + return (a & b) + ((a ^ b) >> 1); + } + + /** + * @return Mean without overflow, rounded to the value of smallest magnitude (i.e. mathematical (a+b)/2, using integer division). + */ + public static int meanSml(int a, int b) { + int result = meanLow(a,b); + if (!haveSameEvenness(a, b)) { + // inexact + if (((a&b) < 0) || (((a|b) < 0) && (a+b < 0))) { + // both < 0, or only one is < 0 and it has the largest magnitude + result++; + } + } + return result; + } + + /** + * @return Mean without overflow, rounded to the value of smallest magnitude (i.e. mathematical (a+b)/2, using integer division). + */ + public static long meanSml(long a, long b) { + long result = meanLow(a,b); + if (!haveSameEvenness(a, b)) { + // inexact + if (((a&b) < 0) || (((a|b) < 0) && (a+b < 0))) { + // both < 0, or only one is < 0 and it has the largest magnitude + result++; + } + } + return result; + } + + /** + * Useful because a positive int value could not represent half the width + * of full int range width, which is mathematically Integer.MAX_VALUE+1. + * + * @return Minus half the range width (inclusive, and rounded to the value of smaller magnitude) + * between the specified bounds. + * @throws IllegalArgumentException if min > max. + */ + public static int negHalfWidth(int min, int max) { + if (min > max) { + throw new IllegalArgumentException("min ["+min+"] must be <= max ["+max+"]"); + } + int mean = meanLow(min, max); + return min - mean - ((min^max)&1); + } + + /** + * Useful because a positive long value could not represent half the width + * of full long range width, which is mathematically Long.MAX_VALUE+1. + * + * @return Minus half the range width (inclusive, and rounded to the value of smaller magnitude) + * between the specified bounds. + * @throws IllegalArgumentException if min > max. + */ + public static long negHalfWidth(long min, long max) { + if (min > max) { + throw new IllegalArgumentException("min ["+min+"] must be <= max ["+max+"]"); + } + long mean = meanLow(min, max); + return min - mean - ((min^max)&1); + } + + /** + * This treatment being designed for optimization, the fact that spot + * is a signed power of two is not checked. + * + * @param value A value. + * @param spot A signed power of two (i.e. a value of the form +-2^k, k >= 0). + * @return value % spot, i.e. a value in ]-|spot|,|spot|[. + */ + public static int moduloSignedPowerOfTwo(int value, int spot) { + if (spot == Integer.MIN_VALUE) { + return (value != Integer.MIN_VALUE) ? value : 0; + } else { + int s = (value>>31); + return ((((value+s) ^ s) & (abs(spot)-1)) + s) ^ s; + } + } + + /** + * This treatment being designed for optimization, the fact that spot + * is a signed power of two is not checked. + * + * @param value A value. + * @param spot A signed power of two (i.e. a value of the form +-2^k, k >= 0). + * @return value % spot, i.e. a value in ]-|spot|,|spot|[. + */ + public static long moduloSignedPowerOfTwo(long value, long spot) { + if (spot == Long.MIN_VALUE) { + return (value != Long.MIN_VALUE) ? value : 0; + } else { + long s = (value>>63); + return ((((value+s) ^ s) & (abs(spot)-1)) + s) ^ s; + } + } + + /** + * @param value An integer value > 0. + * @return The integer part of the logarithm, in base 2, of the specified value, + * i.e. a result in [0,30] + * @throws IllegalArgumentException if the specified value is <= 0. + */ + public static int log2(int value) { + if (value <= 0) { + throw new IllegalArgumentException("value ["+value+"] must be > 0"); + } + return 31-Integer.numberOfLeadingZeros(value); + } + + /** + * @param value An integer value > 0. + * @return The integer part of the logarithm, in base 2, of the specified value, + * i.e. a result in [0,62] + * @throws IllegalArgumentException if the specified value is <= 0. + */ + public static int log2(long value) { + if (value <= 0) { + throw new IllegalArgumentException("value ["+value+"] must be > 0"); + } + return 63-Long.numberOfLeadingZeros(value); + } + + /** + * Possibly faster than java.lang.Math.abs(int). + * + * @return The absolute value, except if value is Integer.MIN_VALUE, for which it returns Integer.MIN_VALUE. + */ + public static int abs(int a) { + return (a^(a>>31))-(a>>31); + } + + /** + * Possibly faster than java.lang.Math.abs(long). + * + * @return The absolute value, except if value is Long.MIN_VALUE, for which it returns Long.MIN_VALUE. + */ + public static long abs(long a) { + return (a^(a>>63))-(a>>63); + } + + /** + * @return The negative of the absolute value (always exact). + */ + public static int absNeg(int a) { + return (a>>31)-(a^(a>>31)); + } + + /** + * @return The negative of the absolute value (always exact). + */ + public static long absNeg(long a) { + return (a>>63)-(a^(a>>63)); + } + + /** + * If the specified value is in int range, the returned value is identical. + * + * @return An int hash of the specified value. + */ + public static int intHash(long a) { + if (false) { + // also works + int hash = ((int)(a>>32)) ^ ((int)a); + if (a < 0) { + hash = -hash-1; + } + return hash; + } + int hash = ((int)(a>>32)) + ((int)a); + if (a < 0) { + hash++; + } + return hash; + } + + /** + * @param a An int value. + * @return The specified value as byte. + * @throws ArithmeticException if the specified value is not in [Byte.MIN_VALUE,Byte.MAX_VALUE] range. + */ + public static byte asByte(int a) { + if (a != (byte)a) { + throw new ArithmeticException("overflow: "+a); + } + return (byte)a; + } + + /** + * @param a A long value. + * @return The specified value as int. + * @throws ArithmeticException if the specified value is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. + */ + public static int asInt(long a) { + if (a != (int)a) { + throw new ArithmeticException("overflow: "+a); + } + return (int)a; + } + + /** + * @param a A long value. + * @return The closest int value in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. + */ + public static int toInt(long a) { + if (a != (int)a) { + return (a < 0) ? Integer.MIN_VALUE : Integer.MAX_VALUE; + } + return (int)a; + } + + /** + * @param a An int value. + * @param b An int value. + * @return The mathematical result of a+b. + * @throws ArithmeticException if the mathematical result of a+b is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. + */ + public static int plusExact(int a, int b) { + final int sum = a + b; + // HD 2-12 Overflow iff both arguments + // have the opposite sign of the result. + if (((a ^ sum) & (b ^ sum)) < 0) { + throw new ArithmeticException("overflow: "+a+"+"+b); + } + return sum; + } + + /** + * @param a A long value. + * @param b A long value. + * @return The mathematical result of a+b. + * @throws ArithmeticException if the mathematical result of a+b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. + */ + public static long plusExact(long a, long b) { + final long sum = a + b; + // HD 2-12 Overflow iff both arguments + // have the opposite sign of the result. + if (((a ^ sum) & (b ^ sum)) < 0) { + throw new ArithmeticException("overflow: "+a+"+"+b); + } + return sum; + } + + /** + * @param a An int value. + * @param b An int value. + * @return The int value of [Integer.MIN_VALUE,Integer.MAX_VALUE] range which is the closest to mathematical result of a+b. + */ + public static int plusBounded(int a, int b) { + return toInt(((long)a) + ((long)b)); + } + + /** + * @param a A long value. + * @param b A long value. + * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a+b. + */ + public static long plusBounded(long a, long b) { + final long sum = a + b; + if (((a ^ sum) & (b ^ sum)) < 0) { + return (sum >= 0) ? Long.MIN_VALUE : Long.MAX_VALUE; + } + return sum; + } + + /** + * @param a An int value. + * @param b An int value. + * @return The mathematical result of a-b. + * @throws ArithmeticException if the mathematical result of a-b is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. + */ + public static int minusExact(int a, int b) { + final int diff = a - b; + // HD 2-12 Overflow iff the arguments have different signs and + // the sign of the result is different than the sign of "a". + if (((a ^ b) & (a ^ diff)) < 0) { + throw new ArithmeticException("integer overflow"); + } + return diff; + } + + /** + * @param a A long value. + * @param b A long value. + * @return The mathematical result of a-b. + * @throws ArithmeticException if the mathematical result of a-b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. + */ + public static long minusExact(long a, long b) { + final long diff = a - b; + // HD 2-12 Overflow iff the arguments have different signs and + // the sign of the result is different than the sign of "a". + if (((a ^ b) & (a ^ diff)) < 0) { + throw new ArithmeticException("integer overflow"); + } + return diff; + } + + /** + * @param a An int value. + * @param b An int value. + * @return The int value of [Integer.MIN_VALUE,Integer.MAX_VALUE] range which is the closest to mathematical result of a-b. + */ + public static int minusBounded(int a, int b) { + return toInt(((long)a) - ((long)b)); + } + + /** + * @param a A long value. + * @param b A long value. + * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a-b. + */ + public static long minusBounded(long a, long b) { + final long diff = a - b; + if (((a ^ b) & (a ^ diff)) < 0) { + return (diff >= 0) ? Long.MIN_VALUE : Long.MAX_VALUE; + } + return diff; + } + + /** + * @param a An int value. + * @param b An int value. + * @return The mathematical result of a*b. + * @throws ArithmeticException if the mathematical result of a*b is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. + */ + public static int timesExact(int a, int b) { + final long prod = a * (long)b; + if (prod != (int)prod) { + throw new ArithmeticException("overflow: "+a+"*"+b); + } + return (int)prod; + } + + /** + * @param a A long value. + * @param b A long value. + * @return The mathematical result of a*b. + * @throws ArithmeticException if the mathematical result of a*b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. + */ + public static long timesExact(long a, long b) { + final long prod = a * b; + final long absA = abs(a); + final long absB = abs(b); + if (((absA|absB)>>>31) != 0) { + // Some bits greater than 2^31 that might cause overflow + // Check the result using the divide operator + // and check for the special case of Long.MIN_VALUE * -1 + if (((b != 0) && (prod/b != a)) || + ((a == Long.MIN_VALUE) && (b == -1))) { + throw new ArithmeticException("overflow: "+a+"*"+b); + } + } + return prod; + } + + /** + * @param a An int value. + * @param b An int value. + * @return The int value of [Integer.MIN_VALUE,Integer.MAX_VALUE] range which is the closest to mathematical result of a*b. + */ + public static int timesBounded(int a, int b) { + return (int)(a * (double)b); + } + + /** + * @param a A long value. + * @param b A long value. + * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a*b. + */ + public static long timesBounded(long a, long b) { + final long prod = a * b; + final long absA = abs(a); + final long absB = abs(b); + if (((absA|absB)>>>31) != 0) { + // Some bits greater than 2^31 that might cause overflow + // Check the result using the divide operator + // and check for the special case of Long.MIN_VALUE * -1 + if (((b != 0) && (prod/b != a)) || + ((a == Long.MIN_VALUE) && (b == -1))) { + return ((a^b) >= 0) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + return prod; + } + + /* + * powers + */ + + /** + * Returns the exact result, provided it's in double range, + * i.e. if power is in [-1074,1023]. + * + * @param power An int power. + * @return 2^power as a double, or +-Infinity in case of overflow. + */ + public static double twoPow(int power) { + if (power <= -MAX_DOUBLE_EXPONENT) { // Not normal. + if (power >= MIN_DOUBLE_EXPONENT) { // Subnormal. + return Double.longBitsToDouble(0x0008000000000000L>>(-(power+MAX_DOUBLE_EXPONENT))); + } else { // Underflow. + return 0.0; + } + } else if (power > MAX_DOUBLE_EXPONENT) { // Overflow. + return Double.POSITIVE_INFINITY; + } else { // Normal. + return Double.longBitsToDouble(((long)(power+MAX_DOUBLE_EXPONENT))<<52); + } + } + + /** + * @param power An int power. + * @return 2^power as an int. + * @throws ArithmeticException if the mathematical result + * is not in int range, i.e. if power is not in [0,30]. + */ + public static int twoPowAsIntExact(int power) { + if ((power < 0) || (power > 30)) { + throw new ArithmeticException("integer overflow"); + } + return 1 << power; + } + + /** + * @param power An int power. + * @return 2^power as an int, or the closest power of two in int range + * in case of overflow, i.e. if power is not in [0,30]. + */ + public static int twoPowAsIntBounded(int power) { + power = toRange(0, 30, power); + return 1 << power; + } + + /** + * @param power An int power. + * @return 2^power as a long. + * @throws ArithmeticException if the mathematical result + * is not in long range, i.e. if power is not in [0,62]. + */ + public static long twoPowAsLongExact(int power) { + if ((power < 0) || (power > 62)) { + throw new ArithmeticException("long overflow"); + } + return 1L << power; + } + + /** + * @param power An int power. + * @return 2^power as a long, or the closest power of two in long range + * in case of overflow, i.e. if power is not in [0,62]. + */ + public static long twoPowAsLongBounded(int power) { + power = toRange(0, 62, power); + return 1L << power; + } + + /** + * @param a A value. + * @return a*a. + */ + public static int pow2(int a) { + return a*a; + } + + /** + * @param a A value. + * @return a*a. + */ + public static long pow2(long a) { + return a*a; + } + + /** + * @param a A value. + * @return a*a. + */ + public static float pow2(float a) { + return a*a; + } + + /** + * Strict version. + * + * @param a A value. + * @return a*a. + */ + public static strictfp float pow2_strict(float a) { + return a*a; + } + + /** + * @param a A value. + * @return a*a. + */ + public static double pow2(double a) { + return a*a; + } + + /** + * Strict version. + * + * @param a A value. + * @return a*a. + */ + public static strictfp double pow2_strict(double a) { + return a*a; + } + + /** + * @param a A value. + * @return a*a*a. + */ + public static int pow3(int a) { + return a*a*a; + } + + /** + * @param a A value. + * @return a*a*a. + */ + public static long pow3(long a) { + return a*a*a; + } + + /** + * @param a A value. + * @return a*a*a. + */ + public static float pow3(float a) { + return a*a*a; + } + + /** + * Strict version. + * + * @param a A value. + * @return a*a*a. + */ + public static strictfp float pow3_strict(float a) { + return a*a*a; + } + + /** + * @param a A value. + * @return a*a*a. + */ + public static double pow3(double a) { + return a*a*a; + } + + /** + * Strict version. + * + * @param a A value. + * @return a*a*a. + */ + public static strictfp double pow3_strict(double a) { + return a*a*a; + } + + /* + * Accurate +-m*PI/n. + */ + + /** + * @param angRad An angle, in radians. + * @return angRad + 2*PI, accurately computed. + */ + public static double plus2PI(double angRad) { + if (angRad > -Math.PI) { + // LO then HI, for better accuracy (if starting near 0). + return (angRad + TWOPI_LO) + TWOPI_HI; + } else { + // HI then LO, for better accuracy (if ending near 0). + return (angRad + TWOPI_HI) + TWOPI_LO; + } + } + + /** + * Strict version. + * + * @param angRad An angle, in radians. + * @return angRad + 2*PI, accurately computed. + */ + public static strictfp double plus2PI_strict(double angRad) { + if (angRad > -Math.PI) { + // LO then HI, for better accuracy (if starting near 0). + return (angRad + TWOPI_LO) + TWOPI_HI; + } else { + // HI then LO, for better accuracy (if ending near 0). + return (angRad + TWOPI_HI) + TWOPI_LO; + } + } + + /** + * @param angRad An angle, in radians. + * @return angRad - 2*PI, accurately computed. + */ + public static double minus2PI(double angRad) { + if (angRad < Math.PI) { + // LO then HI, for better accuracy (if starting near 0). + return (angRad - TWOPI_LO) - TWOPI_HI; + } else { + // HI then LO, for better accuracy (if ending near 0). + return (angRad - TWOPI_HI) - TWOPI_LO; + } + } + + /** + * Strict version. + * + * @param angRad An angle, in radians. + * @return angRad - 2*PI, accurately computed. + */ + public static strictfp double minus2PI_strict(double angRad) { + if (angRad < Math.PI) { + // LO then HI, for better accuracy (if starting near 0). + return (angRad - TWOPI_LO) - TWOPI_HI; + } else { + // HI then LO, for better accuracy (if ending near 0). + return (angRad - TWOPI_HI) - TWOPI_LO; + } + } + + /** + * @param angRad An angle, in radians. + * @return angRad + PI, accurately computed. + */ + public static double plusPI(double angRad) { + if (angRad > -Math.PI/2) { + // LO then HI, for better accuracy (if starting near 0). + return (angRad + PI_LO) + PI_HI; + } else { + // HI then LO, for better accuracy (if ending near 0). + return (angRad + PI_HI) + PI_LO; + } + } + + /** + * Strict version. + * + * @param angRad An angle, in radians. + * @return angRad + PI, accurately computed. + */ + public static strictfp double plusPI_strict(double angRad) { + if (angRad > -Math.PI/2) { + // LO then HI, for better accuracy (if starting near 0). + return (angRad + PI_LO) + PI_HI; + } else { + // HI then LO, for better accuracy (if ending near 0). + return (angRad + PI_HI) + PI_LO; + } + } + + /** + * @param angRad An angle, in radians. + * @return angRad - PI, accurately computed. + */ + public static double minusPI(double angRad) { + if (angRad < Math.PI/2) { + // LO then HI, for better accuracy (if starting near 0). + return (angRad - PI_LO) - PI_HI; + } else { + // HI then LO, for better accuracy (if ending near 0). + return (angRad - PI_HI) - PI_LO; + } + } + + /** + * Strict version. + * + * @param angRad An angle, in radians. + * @return angRad - PI, accurately computed. + */ + public static strictfp double minusPI_strict(double angRad) { + if (angRad < Math.PI/2) { + // LO then HI, for better accuracy (if starting near 0). + return (angRad - PI_LO) - PI_HI; + } else { + // HI then LO, for better accuracy (if ending near 0). + return (angRad - PI_HI) - PI_LO; + } + } + + /** + * @param angRad An angle, in radians. + * @return angRad + PI/2, accurately computed. + */ + public static double plusPIO2(double angRad) { + if (angRad > -Math.PI/4) { + // LO then HI, for better accuracy (if starting near 0). + return (angRad + PIO2_LO) + PIO2_HI; + } else { + // HI then LO, for better accuracy (if ending near 0). + return (angRad + PIO2_HI) + PIO2_LO; + } + } + + /** + * Strict version. + * + * @param angRad An angle, in radians. + * @return angRad + PI/2, accurately computed. + */ + public static strictfp double plusPIO2_strict(double angRad) { + if (angRad > -Math.PI/4) { + // LO then HI, for better accuracy (if starting near 0). + return (angRad + PIO2_LO) + PIO2_HI; + } else { + // HI then LO, for better accuracy (if ending near 0). + return (angRad + PIO2_HI) + PIO2_LO; + } + } + + /** + * @param angRad An angle, in radians. + * @return angRad - PI/2, accurately computed. + */ + public static double minusPIO2(double angRad) { + if (angRad < Math.PI/4) { + // LO then HI, for better accuracy (if starting near 0). + return (angRad - PIO2_LO) - PIO2_HI; + } else { + // HI then LO, for better accuracy (if ending near 0). + return (angRad - PIO2_HI) - PIO2_LO; + } + } + + /** + * Strict version. + * + * @param angRad An angle, in radians. + * @return angRad - PI/2, accurately computed. + */ + public static strictfp double minusPIO2_strict(double angRad) { + if (angRad < Math.PI/4) { + // LO then HI, for better accuracy (if starting near 0). + return (angRad - PIO2_LO) - PIO2_HI; + } else { + // HI then LO, for better accuracy (if ending near 0). + return (angRad - PIO2_HI) - PIO2_LO; + } + } + + /* + * toString (radix) + */ + + /** + * @param radix Radix to be checked. + * @return True if does not throw. + * @throws IllegalArgumentException if the specified radix is not in [2,36]. + */ + public static boolean checkRadix(int radix) { + if (!isInRange(Character.MIN_RADIX, Character.MAX_RADIX, radix)) { + throw new IllegalArgumentException("radix ["+radix+"] must be in ["+Character.MIN_RADIX+","+Character.MAX_RADIX+"]"); + } + return true; + } + + /** + * @param radix A radix in [2,36]. + * @return Number of characters (minus sign included) + * to represent the specified value in the specified radix. + */ + public static int computeNbrOfChars(int value, int radix) { + if (value < 0) { + // 1 for sign + return 1 + computeNbrOfDigits_negValue(value, radix); + } else { + return computeNbrOfDigits_negValue(-value, radix); + } + } + + /** + * @param radix A radix in [2,36]. + * @return Number of characters (minus sign included) + * to represent the specified value in the specified radix. + */ + public static int computeNbrOfChars(long value, int radix) { + if (value < 0) { + // 1 for sign + return 1 + computeNbrOfDigits_negValue(value, radix); + } else { + return computeNbrOfDigits_negValue(-value, radix); + } + } + + /** + * @param radix A radix in [2,36]. + * @param paddingUpTo Number of digits (sign excluded) up to which left-padding with zeros is done. + * @return Number of characters (minus sign included) + * to represent the specified value in the specified radix. + */ + public static int computeNbrOfChars(int value, int radix, int paddingUpTo) { + if (value < 0) { + // 1 for sign + return 1 + Math.max(paddingUpTo, computeNbrOfDigits_negValue(value, radix)); + } else { + return Math.max(paddingUpTo, computeNbrOfDigits_negValue(-value, radix)); + } + } + + /** + * @param radix A radix in [2,36]. + * @param paddingUpTo Number of digits (sign excluded) up to which left-padding with zeros is done. + * @return Number of characters (minus sign included) + * to represent the specified value in the specified radix. + */ + public static int computeNbrOfChars(long value, int radix, int paddingUpTo) { + if (value < 0) { + // 1 for sign + return 1 + Math.max(paddingUpTo, computeNbrOfDigits_negValue(value, radix)); + } else { + return Math.max(paddingUpTo, computeNbrOfDigits_negValue(-value, radix)); + } + } + + /** + * @param radix A radix in [2,36]. + * @return Number of digits of the specified value in the specified radix. + */ + public static int computeNbrOfDigits(int value, int radix) { + return computeNbrOfDigits_negValue(-abs(value), radix); + } + + /** + * @param radix A radix in [2,36]. + * @return Number of digits of the specified value in the specified radix. + */ + public static int computeNbrOfDigits(long value, int radix) { + return computeNbrOfDigits_negValue(-abs(value), radix); + } + + /** + * @param radix A radix in [2,36]. + * @param paddingUpTo Number of digits (sign excluded) up to which left-padding with zeros is done. + * @return Number of digits of the specified value in the specified radix, + * including the specified padding. + */ + public static int computeNbrOfDigits(int value, int radix, int paddingUpTo) { + return Math.max(paddingUpTo,computeNbrOfDigits(value, radix)); + } + + /** + * @param radix A radix in [2,36]. + * @param paddingUpTo Number of digits (sign excluded) up to which left-padding with zeros is done. + * @return Number of digits of the specified value in the specified radix, + * including the specified padding. + */ + public static int computeNbrOfDigits(long value, int radix, int paddingUpTo) { + return Math.max(paddingUpTo,computeNbrOfDigits(value, radix)); + } + + /** + * This method just delegates to Integer.toString(int), + * but is defined here to complete the API. + * + * @return String representation of the specified value in base 10. + */ + public static String toString(int value) { + return Integer.toString(value); + } + + /** + * This method just delegates to Long.toString(long), + * but is defined here to complete the API. + * + * @return String representation of the specified value in base 10. + */ + public static String toString(long value) { + return Long.toString(value); + } + + /** + * @param radix A radix in [2,36]. + * @return String representation of the specified value in the specified radix. + * @throws IllegalArgumentException if the specified radix is out of range. + */ + public static String toString(int value, int radix) { + return toString(value, radix, 0); + } + + /** + * @param radix A radix in [2,36]. + * @return String representation of the specified value in the specified radix. + * @throws IllegalArgumentException if the specified radix is out of range. + */ + public static String toString(long value, int radix) { + return toString(value, radix, 0); + } + + /** + * @param radix A radix in [2,36]. + * @param paddingUpTo Number of digits (sign excluded) up to which left-padding with zeros is done. + * @return String representation of the specified value in the specified radix. + * @throws IllegalArgumentException if the specified radix is out of range. + */ + public static String toString(int value, int radix, int paddingUpTo) { + // Only one test if radix+paddingUpTo != 10. + if ((radix+paddingUpTo == 10) && (paddingUpTo == 0)) { + // Using JDK's optimized algorithm. + return Integer.toString(value); + } + + int negValue; + final int signSize; + final boolean negative = (value < 0); + if (negative) { + negValue = value; + signSize = 1; + } else { + negValue = -value; + signSize = 0; + } + // Faster if we just use max possible number of characters (33), + // but we prefer to take care of garbage's memory footprint. + // Checks radix. + final int nbrOfChars = signSize + Math.max(paddingUpTo, computeNbrOfDigits_negValue(negValue, radix)); + + final char[] chars = new char[nbrOfChars]; + + int charPos = nbrOfChars; + + final boolean radixIsPowerOfTwo = ((radix & (radix-1)) == 0); + // Not allowing Integer.MIN_VALUE so it can be negated. + if (radixIsPowerOfTwo && (negValue != Integer.MIN_VALUE)) { + final int mask = radix-1; + final int divShift = DIV_SHIFT_BY_RADIX[radix]; + while (negValue <= -radix) { + chars[--charPos] = CHAR_BY_DIGIT[(int)((-negValue) & mask)]; + negValue = -((-negValue) >> divShift); + } + } else { + while (negValue <= -radix) { + chars[--charPos] = CHAR_BY_DIGIT[(int)(-(negValue % radix))]; + negValue /= radix; + } + } + chars[--charPos] = CHAR_BY_DIGIT[(int)(-negValue)]; + + while (charPos > signSize) { + chars[--charPos] = '0'; + } + + if (negative) { + chars[0] = '-'; + } + + return new String(chars); + } + + /** + * @param radix A radix in [2,36]. + * @param paddingUpTo Number of digits (sign excluded) up to which left-padding with zeros is done. + * @return String representation of the specified value in the specified radix. + * @throws IllegalArgumentException if the specified radix is out of range. + */ + public static String toString(long value, int radix, int paddingUpTo) { + // Only one test if radix+paddingUpTo != 10. + if ((radix+paddingUpTo == 10) && (paddingUpTo == 0)) { + // Using JDK's optimized algorithm. + return Long.toString(value); + } + + long negValue; + final int signSize; + final boolean negative = (value < 0); + if (negative) { + negValue = value; + signSize = 1; + } else { + negValue = -value; + signSize = 0; + } + // Checks radix. + final int nbrOfChars = signSize + Math.max(paddingUpTo, computeNbrOfDigits_negValue(negValue, radix)); + + final char[] chars = new char[nbrOfChars]; + + int charPos = nbrOfChars; + + final boolean radixIsPowerOfTwo = ((radix & (radix-1)) == 0); + // Not allowing Long.MIN_VALUE so it can be negated. + if (radixIsPowerOfTwo && (negValue != Long.MIN_VALUE)) { + final int mask = radix-1; + final int divShift = DIV_SHIFT_BY_RADIX[radix]; + while (negValue <= -radix) { + chars[--charPos] = CHAR_BY_DIGIT[(int)((-negValue) & mask)]; + negValue = -((-negValue) >> divShift); + } + } else { + while (negValue <= -radix) { + chars[--charPos] = CHAR_BY_DIGIT[(int)(-(negValue % radix))]; + negValue /= radix; + } + } + chars[--charPos] = CHAR_BY_DIGIT[(int)(-negValue)]; + + while (charPos > signSize) { + chars[--charPos] = '0'; + } + + if (negative) { + chars[0] = '-'; + } + + return new String(chars); + } + + /* + * toString (bits) + */ + + /** + * @param firstBitPos First bit position (inclusive). + * @param lastBitPosExcl Last bit position (exclusive). + * @return True if does not throw. + * @throws IllegalArgumentException if the specified bit range does not fit in a byte. + */ + public static boolean checkBitPositionsByte(int firstBitPos, int lastBitPosExcl) { + return checkBitPositions(firstBitPos, lastBitPosExcl, 8); + } + + /** + * @param firstBitPos First bit position (inclusive). + * @param lastBitPosExcl Last bit position (exclusive). + * @return True if does not throw. + * @throws IllegalArgumentException if the specified bit range does not fit in a short. + */ + public static boolean checkBitPositionsShort(int firstBitPos, int lastBitPosExcl) { + return checkBitPositions(firstBitPos, lastBitPosExcl, 16); + } + + /** + * @param firstBitPos First bit position (inclusive). + * @param lastBitPosExcl Last bit position (exclusive). + * @return True if does not throw. + * @throws IllegalArgumentException if the specified bit range does not fit in an int. + */ + public static boolean checkBitPositionsInt(int firstBitPos, int lastBitPosExcl) { + return checkBitPositions(firstBitPos, lastBitPosExcl, 32); + } + + /** + * @param firstBitPos First bit position (inclusive). + * @param lastBitPosExcl Last bit position (exclusive). + * @return True if does not throw. + * @throws IllegalArgumentException if the specified bit range does not fit in a long. + */ + public static boolean checkBitPositionsLong(int firstBitPos, int lastBitPosExcl) { + return checkBitPositions(firstBitPos, lastBitPosExcl, 64); + } + + /** + * @return String representation of specified bits, in big endian. + */ + public static String toStringBits(byte bits) { + final char[] chars = new char[8]; + int bitIndex = 8; + while (--bitIndex >= 0) { + chars[7-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); + } + return new String(chars); + } + + /** + * @return String representation of specified bits, in big endian. + */ + public static String toStringBits(short bits) { + final char[] chars = new char[16]; + int bitIndex = 16; + while (--bitIndex >= 0) { + chars[15-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); + } + return new String(chars); + } + + /** + * @return String representation of specified bits, in big endian. + */ + public static String toStringBits(int bits) { + final char[] chars = new char[32]; + int bitIndex = 32; + while (--bitIndex >= 0) { + chars[31-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); + } + return new String(chars); + } + + /** + * @return String representation of specified bits, in big endian. + */ + public static String toStringBits(long bits) { + final char[] chars = new char[64]; + int bitIndex = 64; + while (--bitIndex >= 0) { + chars[63-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); + } + return new String(chars); + } + + /** + * @param firstBitPos First bit position (inclusive). + * @param lastBitPosExcl Last bit position (exclusive). + * @param bigEndian True for bits to be added in big endian order (MSBit to LSBit) + * false for little endian order. + * @param padding True if underscores must be added instead of out-of-range bits, + * false to just add characters corresponding to in-range bits. + * @return String representation of specified bits. + */ + public static String toStringBits( + byte bits, + int firstBitPos, + int lastBitPosExcl, + boolean bigEndian, + boolean padding) { + checkBitPositionsByte(firstBitPos, lastBitPosExcl); + return toStringBits_0_32_bitPosAlreadyChecked(8,bits, firstBitPos, lastBitPosExcl, bigEndian, padding); + } + + /** + * @param firstBitPos First bit position (inclusive). + * @param lastBitPosExcl Last bit position (exclusive). + * @param bigEndian True for bits to be added in big endian order (MSBit to LSBit) + * false for little endian order. + * @param padding True if underscores must be added instead of out-of-range bits, + * false to just add characters corresponding to in-range bits. + * @return String representation of specified bits. + */ + public static String toStringBits( + short bits, + int firstBitPos, + int lastBitPosExcl, + boolean bigEndian, + boolean padding) { + checkBitPositionsShort(firstBitPos, lastBitPosExcl); + return toStringBits_0_32_bitPosAlreadyChecked(16,bits, firstBitPos, lastBitPosExcl, bigEndian, padding); + } + + /** + * @param firstBitPos First bit position (inclusive). + * @param lastBitPosExcl Last bit position (exclusive). + * @param bigEndian True for bits to be added in big endian order (MSBit to LSBit) + * false for little endian order. + * @param padding True if underscores must be added instead of out-of-range bits, + * false to just add characters corresponding to in-range bits. + * @return String representation of specified bits. + */ + public static String toStringBits( + int bits, + int firstBitPos, + int lastBitPosExcl, + boolean bigEndian, + boolean padding) { + checkBitPositionsInt(firstBitPos, lastBitPosExcl); + return toStringBits_0_32_bitPosAlreadyChecked(32,bits, firstBitPos, lastBitPosExcl, bigEndian, padding); + } + + /** + * @param firstBitPos First bit position (inclusive). + * @param lastBitPosExcl Last bit position (exclusive). + * @param bigEndian True for bits to be added in big endian order (MSBit to LSBit) + * false for little endian order. + * @param padding True if underscores must be added instead of out-of-range bits, + * false to just add characters corresponding to in-range bits. + * @return String representation of specified bits. + */ + public static String toStringBits( + long bits, + int firstBitPos, + int lastBitPosExcl, + boolean bigEndian, + boolean padding) { + checkBitPositionsLong(firstBitPos, lastBitPosExcl); + final int bitSize = 64; + final int bitSizeM1 = bitSize-1; + final int lastBitPos = lastBitPosExcl-1; + if (padding) { + final int nbrOfChars = bitSize; + final char[] chars = new char[nbrOfChars]; + int bitIndex = bitSizeM1; + if (bigEndian) { + final int firstBitIndex = bitSizeM1-lastBitPos; + final int lastBitIndex = bitSizeM1-firstBitPos; + while (bitIndex > lastBitIndex) { + chars[bitSizeM1-bitIndex] = '_'; + --bitIndex; + } + while (bitIndex >= firstBitIndex) { + chars[bitSizeM1-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); + --bitIndex; + } + while (bitIndex >= 0) { + chars[bitSizeM1-bitIndex] = '_'; + --bitIndex; + } + } else { + while (bitIndex > lastBitPos) { + chars[bitIndex] = '_'; + --bitIndex; + } + while (bitIndex >= firstBitPos) { + chars[bitIndex] = (char)('0'+((bits>>bitIndex)&1)); + --bitIndex; + } + while (bitIndex >= 0) { + chars[bitIndex] = '_'; + --bitIndex; + } + } + return new String(chars); + } else { + final int nbrOfChars = (lastBitPosExcl - firstBitPos); + final char[] chars = new char[nbrOfChars]; + if (bigEndian) { + final int firstBitIndex = bitSizeM1-lastBitPos; + final int lastBitIndex = bitSizeM1-firstBitPos; + int bitIndex = lastBitIndex; + while (bitIndex >= firstBitIndex) { + chars[lastBitIndex-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); + --bitIndex; + } + } else { + int bitIndex = lastBitPos; + while (bitIndex >= firstBitPos) { + chars[bitIndex-firstBitPos] = (char)('0'+((bits>>bitIndex)&1)); + --bitIndex; + } + } + return new String(chars); + } + } + + /* + * toString (floating points) + * + * toStringCSN(double) and toStringNoCSN(double) + * could be made faster, by using directly internals + * of Double.toString(double), but this would require + * copy-paste of much tricky code from JDK, and + * the overhead of our little rework is relatively + * negligible. + */ + + /** + * @param value A double value. + * @return String representing the specified value, + * using "computerized scientific notation", + * which Double.toString(double) uses for non-infinite + * values, when |value| < 1e-3 or |value| >= 1e7. + */ + public static String toStringCSN(double value) { + // Quick case (also to get rid of +-0.0, + // for which Double.toString(double) doesn't use CSN). + if (value == 0.0) { + if (Double.doubleToRawLongBits(value) < 0) { + return "-0.0E0"; + } else { + return "0.0E0"; + } + } + + final double abs = Math.abs(value); + if ((abs >= NO_CSN_MIN_BOUND_INCL) && (abs < NO_CSN_MAX_BOUND_EXCL)) { + final boolean neg = (value < 0.0); + + final String rawAbs = Double.toString(abs); + if (abs >= 1.0) { + /* + * 0123456 + * 12.3456 ===> 1.23456E1 + * 123.0 ===> 1.23E2 + */ + final int dotIndex = rawAbs.indexOf((int)'.'); + final int powerOfTen = dotIndex-1; + final StringBuilder sb = new StringBuilder(); + if (neg) { + sb.append('-'); + } + // Adding unit-or-above digits, with dot after first one. + sb.append(rawAbs.charAt(0)); + sb.append('.'); + sb.append(rawAbs,1,dotIndex); + if ((value != (int)value) || (abs < 10.0)) { + // Adding below-unit digits (possibly just 0 if abs < 10.0, + // to end up for example with "3.0E0" instead of "3.E0"). + sb.append(rawAbs,dotIndex+1,rawAbs.length()); + } + sb.append('E'); + sb.append(CHAR_BY_DIGIT[powerOfTen]); + return sb.toString(); + } else { + /* + * 012345678 + * 0.0123456 ===> 1.23456E-2 + * 0.01 ===> 1.0E-2 + */ + int nonZeroIndex = 1; + while (rawAbs.charAt(++nonZeroIndex) == '0') { + } + // Negative. + final int powerOfTen = 1-nonZeroIndex; + final int nbrOfSignificantDigitsPastDot = (rawAbs.length() - (nonZeroIndex+1)); + final StringBuilder sb = new StringBuilder(); + if (neg) { + sb.append('-'); + } + sb.append(rawAbs.charAt(nonZeroIndex)); + sb.append('.'); + if (nbrOfSignificantDigitsPastDot > 0) { + // If bug 4428022 make rawAbs being something like "0.0010", + // we add the last '0' here after the dot, which is fine. + sb.append(rawAbs,nonZeroIndex+1,rawAbs.length()); + } else { + sb.append('0'); + } + sb.append("E-"); + sb.append(CHAR_BY_DIGIT[-powerOfTen]); + return sb.toString(); + } + } else { + return Double.toString(value); + } + } + + /** + * @param value A double value. + * @return String representing the specified value, + * not in "computerized scientific notation", + * which Double.toString(double) uses for non-infinite + * values, when |value| < 1e-3 or |value| >= 1e7. + */ + public static String toStringNoCSN(double value) { + // Quick case. + // Should also work with long instead of int, + // but less obvious (due to roundings...), + // and we just want to speed up the more common + // case of "small" integer values. + final int intValue = (int)value; + if (value == intValue) { + if (value == 0.0) { + if (Double.doubleToRawLongBits(value) < 0) { + return "-0.0"; + } else { + return "0.0"; + } + } else { + return Integer.toString(intValue)+".0"; + } + } + + final String raw = Double.toString(value); + final double abs = Math.abs(value); + if (abs >= NO_CSN_MAX_BOUND_EXCL) { + if (abs == Double.POSITIVE_INFINITY) { + return raw; + } + /* + * 0123456789 + * 1.234567E5 ===> 123456.7 + * 1.23456E5 ===> 123456.0 (adding 0) + * 1.23E5 ===> 123000.0 + * 1.0E5 ===> 100000.0 + */ + // "." close to start, so using indexOf. + final int dotIndex = raw.indexOf((int)'.'); + // "E" close to end, so using lastIndexOf. + final int eIndex = raw.lastIndexOf((int)'E'); + final int powerOfTen = Integer.parseInt(raw.substring(eIndex+1)); + final int nbrOfSignificantLoDigits = (eIndex - dotIndex - 1); + final int nbrOfZerosToAddBeforeDot = (powerOfTen - nbrOfSignificantLoDigits); + + int start; + int end; + + final StringBuilder sb = new StringBuilder(); + sb.append(raw,0,dotIndex); + if (nbrOfZerosToAddBeforeDot >= 0) { + // Can copy all digits that were between '.' and 'E'. + sb.append(raw,dotIndex+1,eIndex); + for (int i=0;i 0.0001234 + * 1.0E-4 ===> 0.0001 + */ + // "." close to start, so using indexOf. + final int dotIndex = raw.indexOf((int)'.'); + // "E" close to end, so using lastIndexOf. + final int eIndex = raw.lastIndexOf((int)'E'); + // Negative. + final int powerOfTen = Integer.parseInt(raw.substring(eIndex+1)); + final int nbrOfZerosToAddAfterDot = (-powerOfTen-1); + + final StringBuilder sb = new StringBuilder(); + if (value < 0.0) { + sb.append("-0."); + } else { + sb.append("0."); + } + for (int i=0;i>(32-bitSize)); + } + + private static long minSignedLongForBitSize_noCheck(int bitSize) { + // i.e. (-1L<<(bitSize-1)) + return (Long.MIN_VALUE>>(64-bitSize)); + } + + private static int maxSignedIntForBitSize_noCheck(int bitSize) { + // i.e. (1<<(bitSize-1))-1 + return (Integer.MAX_VALUE>>(32-bitSize)); + } + + private static long maxSignedLongForBitSize_noCheck(int bitSize) { + // i.e. (1L<<(bitSize-1))-1 + return (Long.MAX_VALUE>>(64-bitSize)); + } + + /* + * + */ + + /** + * @throws IllegalArgumentException if the specified radix is out of range. + */ + private static int computeNbrOfDigits_negValue(int negValue, int radix) { + checkRadix(radix); + final int maxNbrOfDigits = MAX_NBR_OF_NEG_INT_DIGITS_BY_RADIX[radix]; + int p = radix; + for (int i=1;i -p) { + return i; + } + p *= radix; + } + return maxNbrOfDigits; + } + + /** + * @throws IllegalArgumentException if the specified radix is out of range. + */ + private static int computeNbrOfDigits_negValue(long negValue, int radix) { + checkRadix(radix); + final int maxNbrOfDigits = MAX_NBR_OF_NEG_LONG_DIGITS_BY_RADIX[radix]; + long p = radix; + for (int i=1;i -p) { + return i; + } + p *= radix; + } + return maxNbrOfDigits; + } + + /* + * + */ + + private static boolean checkBitPositions(int firstBitPos, int lastBitPosExcl, int bitSize) { + if ((firstBitPos < 0) || (firstBitPos > lastBitPosExcl) || (lastBitPosExcl > bitSize)) { + throw new IllegalArgumentException( + "bit positions (first="+firstBitPos+",lastExcl="+lastBitPosExcl + +") must verify 0 <= first <= lastExcl <= "+bitSize); + } + return true; + } + + /** + * Common method for byte, short and int. + * Could be a bit faster to have specific methods for byte and short, + * but not much, and that would also make more messy (byte-)code. + * + * @param bitSize Must be in [0,32]. + */ + private static String toStringBits_0_32_bitPosAlreadyChecked( + int bitSize, + int bits, + int firstBitPos, + int lastBitPosExcl, + boolean bigEndian, + boolean padding) { + final int bitSizeM1 = bitSize-1; + final int lastBitPos = lastBitPosExcl-1; + if (padding) { + final int nbrOfChars = bitSize; + final char[] chars = new char[nbrOfChars]; + int bitIndex = bitSizeM1; + if (bigEndian) { + final int firstBitIndex = bitSizeM1-lastBitPos; + final int lastBitIndex = bitSizeM1-firstBitPos; + while (bitIndex > lastBitIndex) { + chars[bitSizeM1-bitIndex] = '_'; + --bitIndex; + } + while (bitIndex >= firstBitIndex) { + chars[bitSizeM1-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); + --bitIndex; + } + while (bitIndex >= 0) { + chars[bitSizeM1-bitIndex] = '_'; + --bitIndex; + } + } else { + while (bitIndex > lastBitPos) { + chars[bitIndex] = '_'; + --bitIndex; + } + while (bitIndex >= firstBitPos) { + chars[bitIndex] = (char)('0'+((bits>>bitIndex)&1)); + --bitIndex; + } + while (bitIndex >= 0) { + chars[bitIndex] = '_'; + --bitIndex; + } + } + return new String(chars); + } else { + final int nbrOfChars = (lastBitPosExcl - firstBitPos); + final char[] chars = new char[nbrOfChars]; + if (bigEndian) { + final int firstBitIndex = bitSizeM1-lastBitPos; + final int lastBitIndex = bitSizeM1-firstBitPos; + int bitIndex = lastBitIndex; + while (bitIndex >= firstBitIndex) { + chars[lastBitIndex-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); + --bitIndex; + } + } else { + int bitIndex = lastBitPos; + while (bitIndex >= firstBitPos) { + chars[bitIndex-firstBitPos] = (char)('0'+((bits>>bitIndex)&1)); + --bitIndex; + } + } + return new String(chars); + } + } +} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/StrictFastMath.java b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/StrictFastMath.java new file mode 100644 index 000000000..a61ac9772 --- /dev/null +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/StrictFastMath.java @@ -0,0 +1,2998 @@ +/* + * 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.jafama; + +/** + * Strict versions of FastMath methods. + * Cf. README.txt for more info. + */ +public final strictfp class StrictFastMath extends CmnFastMath { + + /* + * We use strictfp for the whole class: + * - for simplicity, + * - to reduce strictfp/non-strictfp switching, which can add overhead, + * when these treatments are used from within strictfp code, + * - to make sure that we only use and return non-extended values, + * else if strictfp gets added later to some treatments they might then + * behave differently due to no longer being inlinable into FP-wide + * expressions, + * - to make sure we don't mistakenly not use it. + */ + + //-------------------------------------------------------------------------- + // CONFIGURATION + //-------------------------------------------------------------------------- + + private static final boolean USE_JDK_MATH = SFM_USE_JDK_MATH; + + private static final boolean USE_REDEFINED_LOG = SFM_USE_REDEFINED_LOG; + + private static final boolean USE_REDEFINED_SQRT = SFM_USE_REDEFINED_SQRT; + + private static final boolean USE_POWTABS_FOR_ASIN = SFM_USE_POWTABS_FOR_ASIN; + + //-------------------------------------------------------------------------- + // PUBLIC METHODS + //-------------------------------------------------------------------------- + + /* + * trigonometry + */ + + /** + * @param angle Angle in radians. + * @return Angle sine. + */ + public static double sin(double angle) { + if (USE_JDK_MATH) { + return StrictMath.sin(angle); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + if (angle > SIN_COS_MAX_VALUE_FOR_INT_MODULO) { + if (false) { + // Can give very bad relative error near PI (mod 2*PI). + angle = remainderTwoPi(angle); + if (angle < 0.0) { + angle = -angle; + negateResult = !negateResult; + } + } else { + final long remAndQuad = remainderPiO2(angle); + angle = decodeRemainder(remAndQuad); + final double sin; + final int q = decodeQuadrant(remAndQuad); + if (q == 0) { + sin = sin(angle); + } else if (q == 1) { + sin = cos(angle); + } else if (q == 2) { + sin = -sin(angle); + } else { + sin = -cos(angle); + } + return (negateResult ? -sin : sin); + } + } + // index: possibly outside tables range. + int index = (int)(angle * SIN_COS_INDEXER + 0.5); + double delta = (angle - index * SIN_COS_DELTA_HI) - index * SIN_COS_DELTA_LO; + // Making sure index is within tables range. + // Last value of each table is the same than first, + // so we ignore it (tabs size minus one) for modulo. + index &= (SIN_COS_TABS_SIZE-2); // index % (SIN_COS_TABS_SIZE-1) + double indexSin = MyTSinCos.sinTab[index]; + double indexCos = MyTSinCos.cosTab[index]; + double result = indexSin + delta * (indexCos + delta * (-indexSin * ONE_DIV_F2 + delta * (-indexCos * ONE_DIV_F3 + delta * indexSin * ONE_DIV_F4))); + return negateResult ? -result : result; + } + + /** + * Quick sin, with accuracy of about 1.6e-3 (PI/) + * for |angle| < 6588395.0 (Integer.MAX_VALUE * (2*PI/) - 2) + * (- 2 due to removing PI/2 before using cosine tab), + * and no accuracy at all for larger values. + * + * @param angle Angle in radians. + * @return Angle sine. + */ + public static double sinQuick(double angle) { + if (USE_JDK_MATH) { + return StrictMath.sin(angle); + } + return MyTSinCos.cosTab[((int)(Math.abs(angle-Math.PI/2) * SIN_COS_INDEXER + 0.5)) & (SIN_COS_TABS_SIZE-2)]; + } + + /** + * @param angle Angle in radians. + * @return Angle cosine. + */ + public static double cos(double angle) { + if (USE_JDK_MATH) { + return StrictMath.cos(angle); + } + angle = Math.abs(angle); + if (angle > SIN_COS_MAX_VALUE_FOR_INT_MODULO) { + if (false) { + // Can give very bad relative error near PI (mod 2*PI). + angle = remainderTwoPi(angle); + if (angle < 0.0) { + angle = -angle; + } + } else { + final long remAndQuad = remainderPiO2(angle); + angle = decodeRemainder(remAndQuad); + final double cos; + final int q = decodeQuadrant(remAndQuad); + if (q == 0) { + cos = cos(angle); + } else if (q == 1) { + cos = -sin(angle); + } else if (q == 2) { + cos = -cos(angle); + } else { + cos = sin(angle); + } + return cos; + } + } + // index: possibly outside tables range. + int index = (int)(angle * SIN_COS_INDEXER + 0.5); + double delta = (angle - index * SIN_COS_DELTA_HI) - index * SIN_COS_DELTA_LO; + // Making sure index is within tables range. + // Last value of each table is the same than first, + // so we ignore it (tabs size minus one) for modulo. + index &= (SIN_COS_TABS_SIZE-2); // index % (SIN_COS_TABS_SIZE-1) + double indexCos = MyTSinCos.cosTab[index]; + double indexSin = MyTSinCos.sinTab[index]; + return indexCos + delta * (-indexSin + delta * (-indexCos * ONE_DIV_F2 + delta * (indexSin * ONE_DIV_F3 + delta * indexCos * ONE_DIV_F4))); + } + + /** + * Quick cos, with accuracy of about 1.6e-3 (PI/) + * for |angle| < 6588397.0 (Integer.MAX_VALUE * (2*PI/)), + * and no accuracy at all for larger values. + * + * @param angle Angle in radians. + * @return Angle cosine. + */ + public static double cosQuick(double angle) { + if (USE_JDK_MATH) { + return StrictMath.cos(angle); + } + return MyTSinCos.cosTab[((int)(Math.abs(angle) * SIN_COS_INDEXER + 0.5)) & (SIN_COS_TABS_SIZE-2)]; + } + + /** + * Computes sine and cosine together. + * + * @param angle Angle in radians. + * @param cosine (out) Angle cosine. + * @return Angle sine. + */ + public static double sinAndCos(double angle, DoubleWrapper cosine) { + if (USE_JDK_MATH) { + cosine.value = StrictMath.cos(angle); + return StrictMath.sin(angle); + } + // Using the same algorithm than sin(double) method, + // and computing also cosine at the end. + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + if (angle > SIN_COS_MAX_VALUE_FOR_INT_MODULO) { + if (false) { + // Can give very bad relative error near PI (mod 2*PI). + angle = remainderTwoPi(angle); + if (angle < 0.0) { + angle = -angle; + negateResult = !negateResult; + } + } else { + final long remAndQuad = remainderPiO2(angle); + angle = decodeRemainder(remAndQuad); + final double sin; + final int q = decodeQuadrant(remAndQuad); + if (q == 0) { + sin = sin(angle); + cosine.value = cos(angle); + } else if (q == 1) { + sin = cos(angle); + cosine.value = -sin(angle); + } else if (q == 2) { + sin = -sin(angle); + cosine.value = -cos(angle); + } else { + sin = -cos(angle); + cosine.value = sin(angle); + } + return (negateResult ? -sin : sin); + } + } + int index = (int)(angle * SIN_COS_INDEXER + 0.5); + double delta = (angle - index * SIN_COS_DELTA_HI) - index * SIN_COS_DELTA_LO; + index &= (SIN_COS_TABS_SIZE-2); // index % (SIN_COS_TABS_SIZE-1) + double indexSin = MyTSinCos.sinTab[index]; + double indexCos = MyTSinCos.cosTab[index]; + // Could factor some multiplications (delta * factorials), but then is less accurate. + cosine.value = indexCos + delta * (-indexSin + delta * (-indexCos * ONE_DIV_F2 + delta * (indexSin * ONE_DIV_F3 + delta * indexCos * ONE_DIV_F4))); + double result = indexSin + delta * (indexCos + delta * (-indexSin * ONE_DIV_F2 + delta * (-indexCos * ONE_DIV_F3 + delta * indexSin * ONE_DIV_F4))); + return negateResult ? -result : result; + } + + /** + * Can have very bad relative error near +-PI/2, + * but of the same magnitude than the relative delta between + * StrictMath.tan(PI/2) and StrictMath.tan(nextDown(PI/2)). + * + * @param angle Angle in radians. + * @return Angle tangent. + */ + public static double tan(double angle) { + if (USE_JDK_MATH) { + return StrictMath.tan(angle); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + if (angle > TAN_MAX_VALUE_FOR_INT_MODULO) { + angle = remainderPi(angle); + if (angle < 0.0) { + angle = -angle; + negateResult = !negateResult; + } + } + // index: possibly outside tables range. + int index = (int)(angle * TAN_INDEXER + 0.5); + double delta = (angle - index * TAN_DELTA_HI) - index * TAN_DELTA_LO; + // Making sure index is within tables range. + // index modulo PI, i.e. 2*(virtual tab size minus one). + index &= (2*(TAN_VIRTUAL_TABS_SIZE-1)-1); // index % (2*(TAN_VIRTUAL_TABS_SIZE-1)) + // Here, index is in [0,2*(TAN_VIRTUAL_TABS_SIZE-1)-1], i.e. indicates an angle in [0,PI[. + if (index > (TAN_VIRTUAL_TABS_SIZE-1)) { + index = (2*(TAN_VIRTUAL_TABS_SIZE-1)) - index; + delta = -delta; + negateResult = !negateResult; + } + double result; + if (index < TAN_TABS_SIZE) { + result = MyTTan.tanTab[index] + + delta * (MyTTan.tanDer1DivF1Tab[index] + + delta * (MyTTan.tanDer2DivF2Tab[index] + + delta * (MyTTan.tanDer3DivF3Tab[index] + + delta * MyTTan.tanDer4DivF4Tab[index]))); + } else { // angle in ]TAN_MAX_VALUE_FOR_TABS,TAN_MAX_VALUE_FOR_INT_MODULO], or angle is NaN + // Using tan(angle) == 1/tan(PI/2-angle) formula: changing angle (index and delta), and inverting. + index = (TAN_VIRTUAL_TABS_SIZE-1) - index; + result = 1/(MyTTan.tanTab[index] + - delta * (MyTTan.tanDer1DivF1Tab[index] + - delta * (MyTTan.tanDer2DivF2Tab[index] + - delta * (MyTTan.tanDer3DivF3Tab[index] + - delta * MyTTan.tanDer4DivF4Tab[index])))); + } + return negateResult ? -result : result; + } + + /** + * @param value Value in [-1,1]. + * @return Value arcsine, in radians, in [-PI/2,PI/2]. + */ + public static double asin(double value) { + if (USE_JDK_MATH) { + return StrictMath.asin(value); + } + boolean negateResult = false; + if (value < 0.0) { + value = -value; + negateResult = true; + } + if (value <= ASIN_MAX_VALUE_FOR_TABS) { + int index = (int)(value * ASIN_INDEXER + 0.5); + double delta = value - index * ASIN_DELTA; + double result = MyTAsin.asinTab[index] + + delta * (MyTAsin.asinDer1DivF1Tab[index] + + delta * (MyTAsin.asinDer2DivF2Tab[index] + + delta * (MyTAsin.asinDer3DivF3Tab[index] + + delta * MyTAsin.asinDer4DivF4Tab[index]))); + return negateResult ? -result : result; + } else if (USE_POWTABS_FOR_ASIN && (value <= ASIN_MAX_VALUE_FOR_POWTABS)) { + int index = (int)(powFast(value * ASIN_POWTABS_ONE_DIV_MAX_VALUE, ASIN_POWTABS_POWER) * ASIN_POWTABS_SIZE_MINUS_ONE + 0.5); + double delta = value - MyTAsinPow.asinParamPowTab[index]; + double result = MyTAsinPow.asinPowTab[index] + + delta * (MyTAsinPow.asinDer1DivF1PowTab[index] + + delta * (MyTAsinPow.asinDer2DivF2PowTab[index] + + delta * (MyTAsinPow.asinDer3DivF3PowTab[index] + + delta * MyTAsinPow.asinDer4DivF4PowTab[index]))); + return negateResult ? -result : result; + } else { // value > ASIN_MAX_VALUE_FOR_TABS, or value is NaN + // This part is derived from fdlibm. + if (value < 1.0) { + double t = (1.0 - value)*0.5; + double p = t*(ASIN_PS0+t*(ASIN_PS1+t*(ASIN_PS2+t*(ASIN_PS3+t*(ASIN_PS4+t*ASIN_PS5))))); + double q = 1.0+t*(ASIN_QS1+t*(ASIN_QS2+t*(ASIN_QS3+t*ASIN_QS4))); + double s = sqrt(t); + double z = s+s*(p/q); + double result = ASIN_PIO2_HI-((z+z)-ASIN_PIO2_LO); + return negateResult ? -result : result; + } else { // value >= 1.0, or value is NaN + if (value == 1.0) { + return negateResult ? -Math.PI/2 : Math.PI/2; + } else { + return Double.NaN; + } + } + } + } + + /** + * If value is not NaN and is outside [-1,1] range, closest value in this range is used. + * + * @param value Value in [-1,1]. + * @return Value arcsine, in radians, in [-PI/2,PI/2]. + */ + public static double asinInRange(double value) { + if (value <= -1.0) { + return -Math.PI/2; + } else if (value >= 1.0) { + return Math.PI/2; + } else { + return asin(value); + } + } + + /** + * @param value Value in [-1,1]. + * @return Value arccosine, in radians, in [0,PI]. + */ + public static double acos(double value) { + if (USE_JDK_MATH) { + return StrictMath.acos(value); + } + return Math.PI/2 - asin(value); + } + + /** + * If value is not NaN and is outside [-1,1] range, + * closest value in this range is used. + * + * @param value Value in [-1,1]. + * @return Value arccosine, in radians, in [0,PI]. + */ + public static double acosInRange(double value) { + if (value <= -1.0) { + return Math.PI; + } else if (value >= 1.0) { + return 0.0; + } else { + return acos(value); + } + } + + /** + * @param value A double value. + * @return Value arctangent, in radians, in [-PI/2,PI/2]. + */ + public static double atan(double value) { + if (USE_JDK_MATH) { + return StrictMath.atan(value); + } + boolean negateResult = false; + if (value < 0.0) { + value = -value; + negateResult = true; + } + if (value == 1.0) { + // We want "exact" result for 1.0. + return negateResult ? -Math.PI/4 : Math.PI/4; + } else if (value <= ATAN_MAX_VALUE_FOR_TABS) { + int index = (int)(value * ATAN_INDEXER + 0.5); + double delta = value - index * ATAN_DELTA; + double result = MyTAtan.atanTab[index] + + delta * (MyTAtan.atanDer1DivF1Tab[index] + + delta * (MyTAtan.atanDer2DivF2Tab[index] + + delta * (MyTAtan.atanDer3DivF3Tab[index] + + delta * MyTAtan.atanDer4DivF4Tab[index]))); + return negateResult ? -result : result; + } else { // value > ATAN_MAX_VALUE_FOR_TABS, or value is NaN + // This part is derived from fdlibm. + if (value < TWO_POW_66) { + double x = -1/value; + double x2 = x*x; + double x4 = x2*x2; + double s1 = x2*(ATAN_AT0+x4*(ATAN_AT2+x4*(ATAN_AT4+x4*(ATAN_AT6+x4*(ATAN_AT8+x4*ATAN_AT10))))); + double s2 = x4*(ATAN_AT1+x4*(ATAN_AT3+x4*(ATAN_AT5+x4*(ATAN_AT7+x4*ATAN_AT9)))); + double result = ATAN_HI3-((x*(s1+s2)-ATAN_LO3)-x); + return negateResult ? -result : result; + } else { // value >= 2^66, or value is NaN + if (value != value) { + return Double.NaN; + } else { + return negateResult ? -Math.PI/2 : Math.PI/2; + } + } + } + } + + /** + * For special values for which multiple conventions could be adopted, + * behaves like StrictMath.atan2(double,double). + * + * @param y Coordinate on y axis. + * @param x Coordinate on x axis. + * @return Angle from x axis positive side to (x,y) position, in radians, in [-PI,PI]. + * Angle measure is positive when going from x axis to y axis (positive sides). + */ + public static double atan2(double y, double x) { + if (USE_JDK_MATH) { + return StrictMath.atan2(y,x); + } + /* + * Using sub-methods, to make method lighter for general case, + * and to avoid JIT-optimization crash on NaN. + */ + if (x > 0.0) { + if (y == 0.0) { + // +-0.0 + return y; + } + if (x == Double.POSITIVE_INFINITY) { + return atan2_pinf_yyy(y); + } else { + return atan(y/x); + } + } else if (x < 0.0) { + if (y == 0.0) { + return signFromBit(y) * Math.PI; + } + if (x == Double.NEGATIVE_INFINITY) { + return atan2_ninf_yyy(y); + } else if (y > 0.0) { + return Math.PI/2 - atan(x/y); + } else if (y < 0.0) { + return -Math.PI/2 - atan(x/y); + } else { + return Double.NaN; + } + } else { + return atan2_yyy_zeroOrNaN(y, x); + } + } + + /** + * Gives same result as StrictMath.toRadians for some particular values + * like 90.0, 180.0 or 360.0, but is faster (no division). + * + * @param angdeg Angle value in degrees. + * @return Angle value in radians. + */ + public static double toRadians(double angdeg) { + if (USE_JDK_MATH) { + return StrictMath.toRadians(angdeg); + } + return angdeg * (Math.PI/180); + } + + /** + * Gives same result as StrictMath.toDegrees for some particular values + * like Math.PI/2, Math.PI or 2*Math.PI, but is faster (no division). + * + * @param angrad Angle value in radians. + * @return Angle value in degrees. + */ + public static double toDegrees(double angrad) { + if (USE_JDK_MATH) { + return StrictMath.toDegrees(angrad); + } + return angrad * (180/Math.PI); + } + + /** + * @param sign Sign of the angle: true for positive, false for negative. + * @param degrees Degrees, in [0,180]. + * @param minutes Minutes, in [0,59]. + * @param seconds Seconds, in [0.0,60.0[. + * @return Angle in radians. + */ + public static double toRadians(boolean sign, int degrees, int minutes, double seconds) { + return toRadians(toDegrees(sign, degrees, minutes, seconds)); + } + + /** + * @param sign Sign of the angle: true for positive, false for negative. + * @param degrees Degrees, in [0,180]. + * @param minutes Minutes, in [0,59]. + * @param seconds Seconds, in [0.0,60.0[. + * @return Angle in degrees. + */ + public static double toDegrees(boolean sign, int degrees, int minutes, double seconds) { + double signFactor = sign ? 1.0 : -1.0; + return signFactor * (degrees + (1.0/60)*(minutes + (1.0/60)*seconds)); + } + + /** + * @param angrad Angle in radians. + * @param degrees (out) Degrees, in [0,180]. + * @param minutes (out) Minutes, in [0,59]. + * @param seconds (out) Seconds, in [0.0,60.0[. + * @return true if the resulting angle in [-180deg,180deg] is positive, false if it is negative. + */ + public static boolean toDMS(double angrad, IntWrapper degrees, IntWrapper minutes, DoubleWrapper seconds) { + // Computing longitude DMS. + double tmp = toDegrees(normalizeMinusPiPi(angrad)); + boolean isNeg = (tmp < 0.0); + if (isNeg) { + tmp = -tmp; + } + degrees.value = (int)tmp; + tmp = (tmp-degrees.value)*60.0; + minutes.value = (int)tmp; + seconds.value = Math.min((tmp-minutes.value)*60.0,DOUBLE_BEFORE_60); + return !isNeg; + } + + /** + * NB: Since 2*Math.PI < 2*PI, a span of 2*Math.PI does not mean full angular range. + * ex.: isInClockwiseDomain(0.0, 2*Math.PI, -1e-20) returns false. + * ---> For full angular range, use a span > 2*Math.PI, like 2*PI_SUP constant of this class. + * + * @param startAngRad An angle, in radians. + * @param angSpanRad An angular span, >= 0.0, in radians. + * @param angRad An angle, in radians. + * @return true if angRad is in the clockwise angular domain going from startAngRad, over angSpanRad, + * extremities included, false otherwise. + */ + public static boolean isInClockwiseDomain(double startAngRad, double angSpanRad, double angRad) { + if (Math.abs(angRad) < -TWO_MATH_PI_IN_MINUS_PI_PI) { + // special case for angular values of small magnitude + if (angSpanRad <= 2*Math.PI) { + if (angSpanRad < 0.0) { + // empty domain + return false; + } + // angSpanRad is in [0,2*PI] + startAngRad = normalizeMinusPiPi(startAngRad); + double endAngRad = normalizeMinusPiPi(startAngRad + angSpanRad); + if (startAngRad <= endAngRad) { + return (angRad >= startAngRad) && (angRad <= endAngRad); + } else { + return (angRad >= startAngRad) || (angRad <= endAngRad); + } + } else { // angSpanRad > 2*Math.PI, or is NaN + return (angSpanRad == angSpanRad); + } + } else { + // general case + return (normalizeZeroTwoPi(angRad - startAngRad) <= angSpanRad); + } + } + + /* + * hyperbolic trigonometry + */ + + /** + * Some properties of sinh(x) = (exp(x)-exp(-x))/2: + * 1) defined on ]-Infinity,+Infinity[ + * 2) result in ]-Infinity,+Infinity[ + * 3) sinh(x) = -sinh(-x) (implies sinh(0) = 0) + * 4) sinh(epsilon) ~= epsilon + * 5) lim(sinh(x),x->+Infinity) = +Infinity + * (y increasing exponentially faster than x) + * 6) reaches +Infinity (double overflow) for x >= 710.475860073944, + * i.e. a bit further than exp(x) + * + * @param value A double value. + * @return Value hyperbolic sine. + */ + public static double sinh(double value) { + if (USE_JDK_MATH) { + return StrictMath.sinh(value); + } + // sinh(x) = (exp(x)-exp(-x))/2 + double h; + if (value < 0.0) { + value = -value; + h = -0.5; + } else { + h = 0.5; + } + if (value < 22.0) { + if (value < TWO_POW_N28) { + return (h < 0.0) ? -value : value; + } else { + // sinh(x) + // = (exp(x)-exp(-x))/2 + // = (exp(x)-1/exp(x))/2 + // = (expm1(x) + 1 - 1/(expm1(x)+1))/2 + // = (expm1(x) + (expm1(x)+1)/(expm1(x)+1) - 1/(expm1(x)+1))/2 + // = (expm1(x) + expm1(x)/(expm1(x)+1))/2 + double t = expm1(value); + // Might be more accurate, if value < 1: return h*((t+t)-t*t/(t+1.0)). + return h * (t + t/(t+1.0)); + } + } else if (value < LOG_DOUBLE_MAX_VALUE) { + return h * exp(value); + } else { + double t = exp(value*0.5); + return (h*t)*t; + } + } + + /** + * Some properties of cosh(x) = (exp(x)+exp(-x))/2: + * 1) defined on ]-Infinity,+Infinity[ + * 2) result in [1,+Infinity[ + * 3) cosh(0) = 1 + * 4) cosh(x) = cosh(-x) + * 5) lim(cosh(x),x->+Infinity) = +Infinity + * (y increasing exponentially faster than x) + * 6) reaches +Infinity (double overflow) for x >= 710.475860073944, + * i.e. a bit further than exp(x) + * + * @param value A double value. + * @return Value hyperbolic cosine. + */ + public static double cosh(double value) { + if (USE_JDK_MATH) { + return StrictMath.cosh(value); + } + // cosh(x) = (exp(x)+exp(-x))/2 + if (value < 0.0) { + value = -value; + } + if (value < LOG_TWO_POW_27) { + if (value < TWO_POW_N27) { + // cosh(x) + // = (exp(x)+exp(-x))/2 + // = ((1+x+x^2/2!+...) + (1-x+x^2/2!-...))/2 + // = 1+x^2/2!+x^4/4!+... + // For value of x small in magnitude, the sum of the terms does not add to 1. + return 1; + } else { + // cosh(x) + // = (exp(x)+exp(-x))/2 + // = (exp(x)+1/exp(x))/2 + double t = exp(value); + return 0.5 * (t+1/t); + } + } else if (value < LOG_DOUBLE_MAX_VALUE) { + return 0.5 * exp(value); + } else { + double t = exp(value*0.5); + return (0.5*t)*t; + } + } + + /** + * Much more accurate than cosh(value)-1, + * for arguments (and results) close to zero. + * + * coshm1(-0.0) = -0.0, for homogeneity with + * acosh1p(-0.0) = -0.0. + * + * @param value A double value. + * @return Value hyperbolic cosine, minus 1. + */ + public static double coshm1(double value) { + // cosh(x)-1 = (exp(x)+exp(-x))/2 - 1 + if (value < 0.0) { + value = -value; + } + if (value < LOG_TWO_POW_27) { + if (value < TWO_POW_N27) { + if (value == 0.0) { + // +-0.0 + return value; + } + // Using (expm1(x)+expm1(-x))/2 + // is not accurate for tiny values, + // for expm1 results are of higher + // magnitude than the result and + // of different signs, such as their + // sum is not accurate. + // cosh(x) - 1 + // = (exp(x)+exp(-x))/2 - 1 + // = ((1+x+x^2/2!+...) + (1-x+x^2/2!-...))/2 - 1 + // = x^2/2!+x^4/4!+... + // ~= x^2 * (1/2 + x^2 * 1/24) + // = x^2 * 0.5 (since x < 2^-27) + return 0.5 * value*value; + } else { + // cosh(x) - 1 + // = (exp(x)+exp(-x))/2 - 1 + // = (exp(x)-1+exp(-x)-1)/2 + // = (expm1(x)+expm1(-x))/2 + return 0.5 * (expm1(value)+expm1(-value)); + } + } else if (value < LOG_DOUBLE_MAX_VALUE) { + return 0.5 * exp(value) - 1.0; + } else { + // No need to subtract 1 from result. + double t = exp(value*0.5); + return (0.5*t)*t; + } + } + + /** + * Computes hyperbolic sine and hyperbolic cosine together. + * + * @param value A double value. + * @param hcosine (out) Value hyperbolic cosine. + * @return Value hyperbolic sine. + */ + public static double sinhAndCosh(double value, DoubleWrapper hcosine) { + if (USE_JDK_MATH) { + hcosine.value = StrictMath.cosh(value); + return StrictMath.sinh(value); + } + // Mixup of sinh and cosh treatments: if you modify them, + // you might want to also modify this. + double h; + if (value < 0.0) { + value = -value; + h = -0.5; + } else { + h = 0.5; + } + final double hsine; + // LOG_TWO_POW_27 = 18.714973875118524 + if (value < LOG_TWO_POW_27) { // test from cosh + // sinh + if (value < TWO_POW_N28) { + hsine = (h < 0.0) ? -value : value; + } else { + double t = expm1(value); + hsine = h * (t + t/(t+1.0)); + } + // cosh + if (value < TWO_POW_N27) { + hcosine.value = 1; + } else { + double t = exp(value); + hcosine.value = 0.5 * (t+1/t); + } + } else if (value < 22.0) { // test from sinh + // Here, value is in [18.714973875118524,22.0[. + double t = expm1(value); + hsine = h * (t + t/(t+1.0)); + hcosine.value = 0.5 * (t+1.0); + } else { + if (value < LOG_DOUBLE_MAX_VALUE) { + hsine = h * exp(value); + } else { + double t = exp(value*0.5); + hsine = (h*t)*t; + } + hcosine.value = Math.abs(hsine); + } + return hsine; + } + + /** + * Some properties of tanh(x) = sinh(x)/cosh(x) = (exp(2*x)-1)/(exp(2*x)+1): + * 1) defined on ]-Infinity,+Infinity[ + * 2) result in ]-1,1[ + * 3) tanh(x) = -tanh(-x) (implies tanh(0) = 0) + * 4) tanh(epsilon) ~= epsilon + * 5) lim(tanh(x),x->+Infinity) = 1 + * 6) reaches 1 (double loss of precision) for x = 19.061547465398498 + * + * @param value A double value. + * @return Value hyperbolic tangent. + */ + public static double tanh(double value) { + if (USE_JDK_MATH) { + return StrictMath.tanh(value); + } + // tanh(x) = sinh(x)/cosh(x) + // = (exp(x)-exp(-x))/(exp(x)+exp(-x)) + // = (exp(2*x)-1)/(exp(2*x)+1) + boolean negateResult = false; + if (value < 0.0) { + value = -value; + negateResult = true; + } + double z; + if (value < TANH_1_THRESHOLD) { + if (value < TWO_POW_N55) { + return negateResult ? -value*(1.0-value) : value*(1.0+value); + } else if (value >= 1) { + z = 1.0-2.0/(expm1(value+value)+2.0); + } else { + double t = expm1(-(value+value)); + z = -t/(t+2.0); + } + } else { + z = (value != value) ? Double.NaN : 1.0; + } + return negateResult ? -z : z; + } + + /** + * Some properties of asinh(x) = log(x + sqrt(x^2 + 1)) + * 1) defined on ]-Infinity,+Infinity[ + * 2) result in ]-Infinity,+Infinity[ + * 3) asinh(x) = -asinh(-x) (implies asinh(0) = 0) + * 4) asinh(epsilon) ~= epsilon + * 5) lim(asinh(x),x->+Infinity) = +Infinity + * (y increasing logarithmically slower than x) + * + * @param value A double value. + * @return Value hyperbolic arcsine. + */ + public static double asinh(double value) { + // asinh(x) = log(x + sqrt(x^2 + 1)) + boolean negateResult = false; + if (value < 0.0) { + value = -value; + negateResult = true; + } + double result; + // (about) smallest possible for + // non-log1p case to be accurate. + if (value < ASINH_LOG1P_THRESHOLD) { + // Around this range, FDLIBM uses + // log1p(value+value*value/(1+sqrt(value*value+1))), + // but it's slower, so we don't use it. + /* + * If x is close to zero, log argument is close to 1, + * so to avoid precision loss we use log1p(double), + * with + * (1+x)^p = 1 + p * x + (p*(p-1))/2! * x^2 + (p*(p-1)*(p-2))/3! * x^3 + ... + * (1+x)^p = 1 + p * x * (1 + (p-1)/2 * x * (1 + (p-2)/3 * x + ...) + * (1+x)^0.5 = 1 + 0.5 * x * (1 + (0.5-1)/2 * x * (1 + (0.5-2)/3 * x + ...) + * (1+x^2)^0.5 = 1 + 0.5 * x^2 * (1 + (0.5-1)/2 * x^2 * (1 + (0.5-2)/3 * x^2 + ...) + * x + (1+x^2)^0.5 = 1 + x * (1 + 0.5 * x * (1 + (0.5-1)/2 * x^2 * (1 + (0.5-2)/3 * x^2 + ...)) + * so + * asinh(x) = log1p(x * (1 + 0.5 * x * (1 + (0.5-1)/2 * x^2 * (1 + (0.5-2)/3 * x^2 + ...))) + */ + final double x = value; + final double x2 = x*x; + // Enough terms for good accuracy, + // given our threshold. + final double argLog1p = (x * + (1 + 0.5 * x + * (1 + (0.5-1)/2 * x2 + * (1 + (0.5-2)/3 * x2 + * (1 + (0.5-3)/4 * x2 + * (1 + (0.5-4)/5 * x2 + )))))); + result = log1p(argLog1p); + } else if (value < ASINH_ACOSH_SQRT_ELISION_THRESHOLD) { + // Around this range, FDLIBM uses + // log(2*value+1/(value+sqrt(value*value+1))), + // but it involves an additional division + // so we don't use it. + result = log(value + sqrt(value*value + 1.0)); + } else { + // log(2*value) would overflow for value > Double.MAX_VALUE/2, + // so we compute otherwise. + result = LOG_2 + log(value); + } + return negateResult ? -result : result; + } + + /** + * Some properties of acosh(x) = log(x + sqrt(x^2 - 1)): + * 1) defined on [1,+Infinity[ + * 2) result in ]0,+Infinity[ (by convention, since cosh(x) = cosh(-x)) + * 3) acosh(1) = 0 + * 4) acosh(1+epsilon) ~= log(1 + sqrt(2*epsilon)) ~= sqrt(2*epsilon) + * 5) lim(acosh(x),x->+Infinity) = +Infinity + * (y increasing logarithmically slower than x) + * + * @param value A double value. + * @return Value hyperbolic arccosine. + */ + public static double acosh(double value) { + if (!(value > 1.0)) { + // NaN, or value <= 1 + if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { + return (value < 1.0) ? Double.NaN : value - 1.0; + } else { + return (value == 1.0) ? 0.0 : Double.NaN; + } + } + double result; + if (value < ASINH_ACOSH_SQRT_ELISION_THRESHOLD) { + // Around this range, FDLIBM uses + // log(2*value-1/(value+sqrt(value*value-1))), + // but it involves an additional division + // so we don't use it. + result = log(value + sqrt(value*value - 1.0)); + } else { + // log(2*value) would overflow for value > Double.MAX_VALUE/2, + // so we compute otherwise. + result = LOG_2 + log(value); + } + return result; + } + + /** + * Much more accurate than acosh(1+value), + * for arguments (and results) close to zero. + * + * acosh1p(-0.0) = -0.0, for homogeneity with + * sqrt(-0.0) = -0.0, which looks about the same + * near 0. + * + * @param value A double value. + * @return Hyperbolic arccosine of (1+value). + */ + public static double acosh1p(double value) { + if (!(value > 0.0)) { + // NaN, or value <= 0. + // If value is -0.0, returning -0.0. + if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { + return (value < 0.0) ? Double.NaN : value; + } else { + return (value == 0.0) ? value : Double.NaN; + } + } + double result; + if (value < (ASINH_ACOSH_SQRT_ELISION_THRESHOLD-1)) { + // acosh(1+x) + // = log((1+x) + sqrt((1+x)^2 - 1)) + // = log(1 + x + sqrt(1 + 2*x + x^2 - 1)) + // = log1p(x + sqrt(2*x + x^2)) + // = log1p(x + sqrt(x * (2 + x)) + result = log1p(value + sqrt(value * (2 + value))); + } else { + result = LOG_2 + log(1+value); + } + return result; + } + + /** + * Some properties of atanh(x) = log((1+x)/(1-x))/2: + * 1) defined on ]-1,1[ + * 2) result in ]-Infinity,+Infinity[ + * 3) atanh(-1) = -Infinity (by continuity) + * 4) atanh(1) = +Infinity (by continuity) + * 5) atanh(epsilon) ~= epsilon + * 6) lim(atanh(x),x->1) = +Infinity + * + * @param value A double value. + * @return Value hyperbolic arctangent. + */ + public static double atanh(double value) { + boolean negateResult = false; + if (value < 0.0) { + value = -value; + negateResult = true; + } + double result; + if (!(value < 1.0)) { + // NaN, or value >= 1 + if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { + result = (value > 1.0) ? Double.NaN : Double.POSITIVE_INFINITY + value; + } else { + result = (value == 1.0) ? Double.POSITIVE_INFINITY : Double.NaN; + } + } else { + // For value < 0.5, FDLIBM uses + // 0.5 * log1p((value+value) + (value+value)*value/(1-value)), + // instead, but this is good enough for us. + // atanh(x) + // = log((1+x)/(1-x))/2 + // = log((1-x+2x)/(1-x))/2 + // = log1p(2x/(1-x))/2 + result = 0.5 * log1p((value+value)/(1.0-value)); + } + return negateResult ? -result : result; + } + + /* + * exponentials + */ + + /** + * @param value A double value. + * @return e^value. + */ + public static double exp(double value) { + if (USE_JDK_MATH) { + return StrictMath.exp(value); + } + // exp(x) = exp([x])*exp(y) + // with [x] the integer part of x, and y = x-[x] + // ===> + // We find an approximation of y, called z. + // ===> + // exp(x) = exp([x])*(exp(z)*exp(epsilon)) + // with epsilon = y - z + // ===> + // We have exp([x]) and exp(z) pre-computed in tables, we "just" have to compute exp(epsilon). + // + // We use the same indexing (cast to int) to compute x integer part and the + // table index corresponding to z, to avoid two int casts. + // Also, to optimize index multiplication and division, we use powers of two, + // so that we can do it with bits shifts. + + if (value > EXP_OVERFLOW_LIMIT) { + return Double.POSITIVE_INFINITY; + } else if (!(value >= EXP_UNDERFLOW_LIMIT)) { + return (value != value) ? Double.NaN : 0.0; + } + + final int indexes = (int)(value*EXP_LO_INDEXING); + + final int valueInt; + if (indexes >= 0) { + valueInt = (indexes>>EXP_LO_INDEXING_DIV_SHIFT); + } else { + valueInt = -((-indexes)>>EXP_LO_INDEXING_DIV_SHIFT); + } + final double hiTerm = MyTExp.expHiTab[valueInt-(int)EXP_UNDERFLOW_LIMIT]; + + final int zIndex = indexes - (valueInt< 0.0) { + if (value == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } + + // For normal values not close to 1.0, we use the following formula: + // log(value) + // = log(2^exponent*1.mantissa) + // = log(2^exponent) + log(1.mantissa) + // = exponent * log(2) + log(1.mantissa) + // = exponent * log(2) + log(1.mantissaApprox) + log(1.mantissa/1.mantissaApprox) + // = exponent * log(2) + log(1.mantissaApprox) + log(1+epsilon) + // = exponent * log(2) + log(1.mantissaApprox) + epsilon-epsilon^2/2+epsilon^3/3-epsilon^4/4+... + // with: + // 1.mantissaApprox <= 1.mantissa, + // log(1.mantissaApprox) in table, + // epsilon = (1.mantissa/1.mantissaApprox)-1 + // + // To avoid bad relative error for small results, + // values close to 1.0 are treated aside, with the formula: + // log(x) = z*(2+z^2*((2.0/3)+z^2*((2.0/5))+z^2*((2.0/7))+...))) + // with z=(x-1)/(x+1) + + double h; + if (value > 0.95) { + if (value < 1.14) { + double z = (value-1.0)/(value+1.0); + double z2 = z*z; + return z*(2+z2*((2.0/3)+z2*((2.0/5)+z2*((2.0/7)+z2*((2.0/9)+z2*((2.0/11))))))); + } + h = 0.0; + } else if (value < DOUBLE_MIN_NORMAL) { + // Ensuring value is normal. + value *= TWO_POW_52; + // log(x*2^52) + // = log(x)-ln(2^52) + // = log(x)-52*ln(2) + h = -52*LOG_2; + } else { + h = 0.0; + } + + int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); + int valueExp = (valueBitsHi>>20)-MAX_DOUBLE_EXPONENT; + // Getting the first LOG_BITS bits of the mantissa. + int xIndex = ((valueBitsHi<<12)>>>(32-LOG_BITS)); + + // 1.mantissa/1.mantissaApprox - 1 + double z = (value * twoPowNormalOrSubnormal(-valueExp)) * MyTLog.logXInvTab[xIndex] - 1; + + z *= (1-z*((1.0/2)-z*((1.0/3)))); + + return h + valueExp * LOG_2 + (MyTLog.logXLogTab[xIndex] + z); + + } else if (value == 0.0) { + return Double.NEGATIVE_INFINITY; + } else { // value < 0.0, or value is NaN + return Double.NaN; + } + } + + /** + * Quick log, with a max relative error of about 1.9e-3 + * for values in ]Double.MIN_NORMAL,+Infinity[, and + * worse accuracy outside this range. + * + * @param value A double value, in ]0,+Infinity[ (strictly positive and finite). + * @return Value logarithm (base e). + */ + public static double logQuick(double value) { + if (USE_JDK_MATH) { + return StrictMath.log(value); + } + /* + * Inverse of Schraudolph's method for exp, is very inaccurate near 1, + * and not that fast (even using floats), especially with added if's + * to deal with values near 1, so we don't use it, and use a simplified + * version of our log's redefined algorithm. + */ + + // Simplified version of log's redefined algorithm: + // log(value) ~= exponent * log(2) + log(1.mantissaApprox) + + double h; + if (value > 0.87) { + if (value < 1.16) { + return 2.0 * (value-1.0)/(value+1.0); + } + h = 0.0; + } else if (value < DOUBLE_MIN_NORMAL) { + value *= TWO_POW_52; + h = -52*LOG_2; + } else { + h = 0.0; + } + + int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); + int valueExp = (valueBitsHi>>20)-MAX_DOUBLE_EXPONENT; + int xIndex = ((valueBitsHi<<12)>>>(32-LOG_BITS)); + + return h + valueExp * LOG_2 + MyTLog.logXLogTab[xIndex]; + } + + /** + * @param value A double value. + * @return Value logarithm (base 10). + */ + public static double log10(double value) { + if (USE_JDK_MATH || (!USE_REDEFINED_LOG)) { + return StrictMath.log10(value); + } + // INV_LOG_10 is < 1, but there is no risk of log(double) + // overflow (positive or negative) while the end result shouldn't, + // since log(Double.MIN_VALUE) and log(Double.MAX_VALUE) have + // magnitudes of just a few hundreds. + return log(value) * INV_LOG_10; + } + + /** + * Much more accurate than log(1+value), + * for arguments (and results) close to zero. + * + * @param value A double value. + * @return Logarithm (base e) of (1+value). + */ + public static double log1p(double value) { + if (USE_JDK_MATH) { + return StrictMath.log1p(value); + } + if (false) { + // This also works. Simpler but a bit slower. + if (value == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } + double valuePlusOne = 1+value; + if (valuePlusOne == 1.0) { + return value; + } else { + return log(valuePlusOne)*(value/(valuePlusOne-1.0)); + } + } + if (value > -1.0) { + if (value == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } + + // ln'(x) = 1/x + // so + // log(x+epsilon) ~= log(x) + epsilon/x + // + // Let u be 1+value rounded: + // 1+value = u+epsilon + // + // log(1+value) + // = log(u+epsilon) + // ~= log(u) + epsilon/value + // We compute log(u) as done in log(double), and then add the corrective term. + + double valuePlusOne = 1.0+value; + if (valuePlusOne == 1.0) { + return value; + } else if (Math.abs(value) < 0.15) { + double z = value/(value+2.0); + double z2 = z*z; + return z*(2+z2*((2.0/3)+z2*((2.0/5)+z2*((2.0/7)+z2*((2.0/9)+z2*((2.0/11))))))); + } + + int valuePlusOneBitsHi = (int)(Double.doubleToRawLongBits(valuePlusOne)>>32) & 0x7FFFFFFF; + int valuePlusOneExp = (valuePlusOneBitsHi>>20)-MAX_DOUBLE_EXPONENT; + // Getting the first LOG_BITS bits of the mantissa. + int xIndex = ((valuePlusOneBitsHi<<12)>>>(32-LOG_BITS)); + + // 1.mantissa/1.mantissaApprox - 1 + double z = (valuePlusOne * twoPowNormalOrSubnormal(-valuePlusOneExp)) * MyTLog.logXInvTab[xIndex] - 1; + + z *= (1-z*((1.0/2)-z*(1.0/3))); + + // Adding epsilon/valuePlusOne to z, + // with + // epsilon = value - (valuePlusOne-1) + // (valuePlusOne + epsilon ~= 1+value (not rounded)) + + return valuePlusOneExp * LOG_2 + MyTLog.logXLogTab[xIndex] + (z + (value - (valuePlusOne-1))/valuePlusOne); + } else if (value == -1.0) { + return Double.NEGATIVE_INFINITY; + } else { // value < -1.0, or value is NaN + return Double.NaN; + } + } + + /* + * powers + */ + + /** + * 1e-13ish accuracy or better on whole double range. + * + * @param value A double value. + * @param power A power. + * @return value^power. + */ + public static double pow(double value, double power) { + if (USE_JDK_MATH) { + return StrictMath.pow(value,power); + } + if (power == 0.0) { + return 1.0; + } else if (power == 1.0) { + return value; + } + if (value <= 0.0) { + // powerInfo: 0 if not integer, 1 if even integer, -1 if odd integer + int powerInfo; + if (Math.abs(power) >= (TWO_POW_52*2)) { + // The binary digit just before comma is outside mantissa, + // thus it is always 0: power is an even integer. + powerInfo = 1; + } else { + // If power's magnitude permits, we cast into int instead of into long, + // as it is faster. + if (Math.abs(power) <= (double)Integer.MAX_VALUE) { + int powerAsInt = (int)power; + if (power == (double)powerAsInt) { + powerInfo = ((powerAsInt & 1) == 0) ? 1 : -1; + } else { // power is not an integer (and not NaN, due to test against Integer.MAX_VALUE) + powerInfo = 0; + } + } else { + long powerAsLong = (long)power; + if (power == (double)powerAsLong) { + powerInfo = ((powerAsLong & 1) == 0) ? 1 : -1; + } else { // power is not an integer, or is NaN + if (power != power) { + return Double.NaN; + } + powerInfo = 0; + } + } + } + + if (value == 0.0) { + if (power < 0.0) { + return (powerInfo < 0) ? 1/value : Double.POSITIVE_INFINITY; + } else { // power > 0.0 (0 and NaN cases already treated) + return (powerInfo < 0) ? value : 0.0; + } + } else { // value < 0.0 + if (value == Double.NEGATIVE_INFINITY) { + if (powerInfo < 0) { // power odd integer + return (power < 0.0) ? -0.0 : Double.NEGATIVE_INFINITY; + } else { // power even integer, or not an integer + return (power < 0.0) ? 0.0 : Double.POSITIVE_INFINITY; + } + } else { + return (powerInfo == 0) ? Double.NaN : powerInfo * exp(power*log(-value)); + } + } + } else { // value > 0.0, or value is NaN + return exp(power*log(value)); + } + } + + /** + * Quick pow, with a max relative error of about 1e-2 + * for value >= Double.MIN_NORMAL and 1e-10 < |value^power| < 1e10, + * of about 6e-2 for value >= Double.MIN_NORMAL and 1e-40 < |value^power| < 1e40, + * and worse accuracy otherwise. + * + * @param value A double value, in ]0,+Infinity[ (strictly positive and finite). + * @param power A double value. + * @return value^power. + */ + public static double powQuick(double value, double power) { + if (USE_JDK_MATH) { + return StrictMath.pow(value,power); + } + return exp(power*logQuick(value)); + } + + /** + * This treatment is somehow accurate for low values of |power|, + * and for |power*getExponent(value)| < 1023 or so (to stay away + * from double extreme magnitudes (large and small)). + * + * @param value A double value. + * @param power A power. + * @return value^power. + */ + public static double powFast(double value, int power) { + if (USE_JDK_MATH) { + return StrictMath.pow(value,power); + } + if (power < 3) { + if (power < 0) { + // Opposite of Integer.MIN_VALUE does not exist as int. + if (power == Integer.MIN_VALUE) { + // Integer.MAX_VALUE = -(power+1) + return 1.0/(powFast(value,Integer.MAX_VALUE) * value); + } else { + return 1.0/powFast(value,-power); + } + } else { + // Here, power is in [0,2]. + if (power == 2) { // Most common case first. + return value * value; + } else if (power == 0) { + return 1.0; + } else { // power == 1 + return value; + } + } + } else { // power >= 4 + double oddRemains = 1.0; + // If power <= 5, faster to finish outside the loop. + while (power > 5) { + // Test if power is odd. + if ((power & 1) != 0) { + oddRemains *= value; + } + value *= value; + power >>= 1; // power = power / 2 + } + // Here, power is in [3,5]. + if (power == 3) { + return oddRemains * value * value * value; + } else { // power in [4,5]. + double v2 = value * value; + if (power == 4) { + return oddRemains * v2 * v2; + } else { // power == 5 + return oddRemains * v2 * v2 * value; + } + } + } + } + + /** + * @param value A float value. + * @return value*value. + */ + public static float pow2(float value) { + return value*value; + } + + /** + * @param value A double value. + * @return value*value. + */ + public static double pow2(double value) { + return value*value; + } + + /** + * @param value A float value. + * @return value*value*value. + */ + public static float pow3(float value) { + return value*value*value; + } + + /** + * @param value A double value. + * @return value*value*value. + */ + public static double pow3(double value) { + return value*value*value; + } + + /* + * roots + */ + + /** + * @param value A double value. + * @return Value square root. + */ + public static double sqrt(double value) { + if (USE_JDK_MATH || (!USE_REDEFINED_SQRT)) { + return StrictMath.sqrt(value); + } + // See cbrt for comments, sqrt uses the same ideas. + + if (!(value > 0.0)) { // value <= 0.0, or value is NaN + if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { + return (value < 0.0) ? Double.NaN : value; + } else { + return (value == 0.0) ? value : Double.NaN; + } + } else if (value == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } + + double h; + if (value < DOUBLE_MIN_NORMAL) { + value *= TWO_POW_52; + h = 2*TWO_POW_N26; + } else { + h = 2.0; + } + + int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); + int valueExponentIndex = (valueBitsHi>>20)+(-MAX_DOUBLE_EXPONENT-MIN_DOUBLE_EXPONENT); + int xIndex = ((valueBitsHi<<12)>>>(32-SQRT_LO_BITS)); + + double result = MyTSqrt.sqrtXSqrtHiTab[valueExponentIndex] * MyTSqrt.sqrtXSqrtLoTab[xIndex]; + double slope = MyTSqrt.sqrtSlopeHiTab[valueExponentIndex] * MyTSqrt.sqrtSlopeLoTab[xIndex]; + value *= 0.25; + + result += (value - result * result) * slope; + result += (value - result * result) * slope; + return h*(result + (value - result * result) * slope); + } + + /** + * Quick sqrt, with with a max relative error of about 3.41e-2 + * for values in [Double.MIN_NORMAL,Double.MAX_VALUE], and worse + * accuracy outside this range. + * + * @param value A double value. + * @return Value square root. + */ + public static double sqrtQuick(double value) { + if (USE_JDK_MATH) { + return StrictMath.sqrt(value); + } + final long bits = Double.doubleToRawLongBits(value); + /* + * Constant determined empirically, using a random-based metaheuristic. + * Should be possible to find a better one. + */ + return Double.longBitsToDouble((bits+4606859074900000000L)>>>1); + } + + /** + * Quick inverse of square root, with a max relative error of about 3.44e-2 + * for values in [Double.MIN_NORMAL,Double.MAX_VALUE], and worse accuracy + * outside this range. + * + * This implementation uses zero step of Newton's method. + * Here are the max relative errors on [Double.MIN_NORMAL,Double.MAX_VALUE] + * depending on number of steps, if you want to copy-paste this code + * and use your own number: + * n=0: about 3.44e-2 + * n=1: about 1.75e-3 + * n=2: about 4.6e-6 + * n=3: about 3.17e-11 + * n=4: about 3.92e-16 + * n=5: about 3.03e-16 + * + * @param value A double value. + * @return Inverse of value square root. + */ + public static double invSqrtQuick(double value) { + if (USE_JDK_MATH) { + return 1/StrictMath.sqrt(value); + } + /* + * http://en.wikipedia.org/wiki/Fast_inverse_square_root + */ + if (false) { + // With one Newton step (much slower than + // 1/Math.sqrt(double) if not optimized). + final double halfInitial = value * 0.5; + long bits = Double.doubleToRawLongBits(value); + // If n=0, 6910474759270000000L might be better (3.38e-2 max relative error). + bits = 0x5FE6EB50C7B537A9L - (bits>>1); + value = Double.longBitsToDouble(bits); + value = value * (1.5 - halfInitial * value * value); // Newton step, can repeat. + return value; + } else { + return Double.longBitsToDouble(0x5FE6EB50C7B537A9L - (Double.doubleToRawLongBits(value)>>1)); + } + } + + /** + * @param value A double value. + * @return Value cubic root. + */ + public static double cbrt(double value) { + if (USE_JDK_MATH) { + return StrictMath.cbrt(value); + } + double h; + if (value < 0.0) { + if (value == Double.NEGATIVE_INFINITY) { + return Double.NEGATIVE_INFINITY; + } + value = -value; + // Making sure value is normal. + if (value < DOUBLE_MIN_NORMAL) { + value *= (TWO_POW_52*TWO_POW_26); + // h = * / + h = -2*TWO_POW_N26; + } else { + h = -2.0; + } + } else { + if (!(value < Double.POSITIVE_INFINITY)) { // value is +Infinity, or value is NaN + return value; + } + // Making sure value is normal. + if (value < DOUBLE_MIN_NORMAL) { + if (value == 0.0) { + // cbrt(0.0) = 0.0, cbrt(-0.0) = -0.0 + return value; + } + value *= (TWO_POW_52*TWO_POW_26); + h = 2*TWO_POW_N26; + } else { + h = 2.0; + } + } + + // Normal value is (2^ * ). + // First member cubic root is computed, and multiplied with an approximation + // of the cubic root of the second member, to end up with a good guess of + // the result before using Newton's (or Archimedes's) method. + // To compute the cubic root approximation, we use the formula "cbrt(value) = cbrt(x) * cbrt(value/x)", + // choosing x as close to value as possible but inferior to it, so that cbrt(value/x) is close to 1 + // (we could iterate on this method, using value/x as new value for each iteration, + // but finishing with Newton's method is faster). + + // Shift and cast into an int, which overall is faster than working with a long. + int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); + int valueExponentIndex = (valueBitsHi>>20)+(-MAX_DOUBLE_EXPONENT-MIN_DOUBLE_EXPONENT); + // Getting the first CBRT_LO_BITS bits of the mantissa. + int xIndex = ((valueBitsHi<<12)>>>(32-CBRT_LO_BITS)); + double result = MyTCbrt.cbrtXCbrtHiTab[valueExponentIndex] * MyTCbrt.cbrtXCbrtLoTab[xIndex]; + double slope = MyTCbrt.cbrtSlopeHiTab[valueExponentIndex] * MyTCbrt.cbrtSlopeLoTab[xIndex]; + + // Lowering values to avoid overflows when using Newton's method + // (we will then just have to return twice the result). + // result^3 = value + // (result/2)^3 = value/8 + value *= 0.125; + // No need to divide result here, as division is factorized in result computation tables. + // result *= 0.5; + + // Newton's method, looking for y = x^(1/p): + // y(n) = y(n-1) + (x-y(n-1)^p) * slope(y(n-1)) + // y(n) = y(n-1) + (x-y(n-1)^p) * (1/p)*(x(n-1)^(1/p-1)) + // y(n) = y(n-1) + (x-y(n-1)^p) * (1/p)*(x(n-1)^((1-p)/p)) + // with x(n-1)=y(n-1)^p, i.e.: + // y(n) = y(n-1) + (x-y(n-1)^p) * (1/p)*(y(n-1)^(1-p)) + // + // For p=3: + // y(n) = y(n-1) + (x-y(n-1)^3) * (1/(3*y(n-1)^2)) + + // To save time, we don't recompute the slope between Newton's method steps, + // as initial slope is good enough for a few iterations. + // + // NB: slope = 1/(3*trueResult*trueResult) + // As we have result = trueResult/2 (to avoid overflows), we have: + // slope = 4/(3*result*result) + // = (4/3)*resultInv*resultInv + // with newResultInv = 1/newResult + // = 1/(oldResult+resultDelta) + // = (oldResultInv)*1/(1+resultDelta/oldResult) + // = (oldResultInv)*1/(1+resultDelta*oldResultInv) + // ~= (oldResultInv)*(1-resultDelta*oldResultInv) + // ===> Successive slopes could be computed without division, if needed, + // by computing resultInv (instead of slope right away) and retrieving + // slopes from it. + + result += (value - result * result * result) * slope; + result += (value - result * result * result) * slope; + return h*(result + (value - result * result * result) * slope); + } + + /** + * @return sqrt(x^2+y^2) without intermediate overflow or underflow. + */ + public static double hypot(double x, double y) { + if (USE_JDK_MATH) { + return StrictMath.hypot(x,y); + } + x = Math.abs(x); + y = Math.abs(y); + // Ensuring x <= y. + if (y < x) { + double a = x; + x = y; + y = a; + } else if (!(y >= x)) { // Testing if we have some NaN. + return hypot_NaN(x, y); + } + + if (y-x == y) { + // x too small to subtract from y. + return y; + } else { + double factor; + if (y > HYPOT_MAX_MAG) { + // y is too large: scaling down. + x *= (1/HYPOT_FACTOR); + y *= (1/HYPOT_FACTOR); + factor = HYPOT_FACTOR; + } else if (x < (1/HYPOT_MAX_MAG)) { + // x is too small: scaling up. + x *= HYPOT_FACTOR; + y *= HYPOT_FACTOR; + factor = (1/HYPOT_FACTOR); + } else { + factor = 1.0; + } + return factor * sqrt(x*x+y*y); + } + } + + /** + * @return sqrt(x^2+y^2+z^2) without intermediate overflow or underflow. + */ + public static double hypot(double x, double y, double z) { + if (USE_JDK_MATH) { + // No simple JDK equivalent. + } + x = Math.abs(x); + y = Math.abs(y); + z = Math.abs(z); + /* + * Considering that z magnitude is the most likely to be the smaller, + * hence ensuring z <= y <= x, and not x <= y <= z, for less swaps. + */ + // Ensuring z <= y. + if (z > y) { + // y < z: swapping y and z + double a = z; + z = y; + y = a; + } else if (!(z <= y)) { // Testing if y or z is NaN. + return hypot_NaN(x, y, z); + } + // Ensuring y <= x. + if (z > x) { + // x < z <= y: moving x + double oldZ = z; + z = x; + double oldY = y; + y = oldZ; + x = oldY; + } else if (y > x) { + // z <= x < y: swapping x and y + double a = y; + y = x; + x = a; + } else if (x != x) { // Testing if x is NaN. + return hypot_NaN(x, y, z); + } + + if (x-y == x) { + // y, hence z, too small to subtract from x. + return x; + } else if (y-z == y) { + // z too small to subtract from y, hence x. + double factor; + if (x > HYPOT_MAX_MAG) { + // x is too large: scaling down. + x *= (1/HYPOT_FACTOR); + y *= (1/HYPOT_FACTOR); + factor = HYPOT_FACTOR; + } else if (y < (1/HYPOT_MAX_MAG)) { + // y is too small: scaling up. + x *= HYPOT_FACTOR; + y *= HYPOT_FACTOR; + factor = (1/HYPOT_FACTOR); + } else { + factor = 1.0; + } + return factor * sqrt(x*x+y*y); + } else { + double factor; + if (x > HYPOT_MAX_MAG) { + // x is too large: scaling down. + x *= (1/HYPOT_FACTOR); + y *= (1/HYPOT_FACTOR); + z *= (1/HYPOT_FACTOR); + factor = HYPOT_FACTOR; + } else if (z < (1/HYPOT_MAX_MAG)) { + // z is too small: scaling up. + x *= HYPOT_FACTOR; + y *= HYPOT_FACTOR; + z *= HYPOT_FACTOR; + factor = (1/HYPOT_FACTOR); + } else { + factor = 1.0; + } + // Adding smaller magnitudes together first. + return factor * sqrt(x*x+(y*y+z*z)); + } + } + + /* + * close values + */ + + /** + * @param value A float value. + * @return Floor of value. + */ + public static float floor(float value) { + final int exponent = getExponent(value); + if (exponent < 0) { + // abs(value) < 1. + if (value < 0.0f) { + return -1.0f; + } else { + // 0.0f, or -0.0f if value is -0.0f + return 0.0f * value; + } + } else if (exponent < 23) { + // A bit faster than using casts. + final int bits = Float.floatToRawIntBits(value); + final int anteCommaBits = bits & (0xFF800000>>exponent); + if ((value < 0.0f) && (anteCommaBits != bits)) { + return Float.intBitsToFloat(anteCommaBits) - 1.0f; + } else { + return Float.intBitsToFloat(anteCommaBits); + } + } else { + // +-Infinity, NaN, or a mathematical integer. + return value; + } + } + + /** + * @param value A double value. + * @return Floor of value. + */ + public static double floor(double value) { + if (USE_JDK_MATH) { + return StrictMath.floor(value); + } + if (ANTI_SLOW_CASTS) { + double valueAbs = Math.abs(value); + if (valueAbs <= (double)Integer.MAX_VALUE) { + if (value > 0.0) { + return (double)(int)value; + } else if (value < 0.0) { + double anteCommaDigits = (double)(int)value; + if (value != anteCommaDigits) { + return anteCommaDigits - 1.0; + } else { + return anteCommaDigits; + } + } else { // value is +-0.0 (not NaN due to test against Integer.MAX_VALUE) + return value; + } + } else if (valueAbs < TWO_POW_52) { + // We split the value in two: + // high part, which is a mathematical integer, + // and the rest, for which we can get rid of the + // post comma digits by casting into an int. + double highPart = ((int)(value * TWO_POW_N26)) * TWO_POW_26; + if (value > 0.0) { + return highPart + (double)((int)(value - highPart)); + } else { + double anteCommaDigits = highPart + (double)((int)(value - highPart)); + if (value != anteCommaDigits) { + return anteCommaDigits - 1.0; + } else { + return anteCommaDigits; + } + } + } else { // abs(value) >= 2^52, or value is NaN + return value; + } + } else { + final int exponent = getExponent(value); + if (exponent < 0) { + // abs(value) < 1. + if (value < 0.0) { + return -1.0; + } else { + // 0.0, or -0.0 if value is -0.0 + return 0.0 * value; + } + } else if (exponent < 52) { + // A bit faster than working on bits. + final long matIntPart = (long)value; + final double matIntToValue = value-(double)matIntPart; + if (matIntToValue >= 0.0) { + return (double)matIntPart; + } else { + return (double)(matIntPart - 1); + } + } else { + // +-Infinity, NaN, or a mathematical integer. + return value; + } + } + } + + /** + * @param value A float value. + * @return Ceiling of value. + */ + public static float ceil(float value) { + return -floor(-value); + } + + /** + * @param value A double value. + * @return Ceiling of value. + */ + public static double ceil(double value) { + if (USE_JDK_MATH) { + return StrictMath.ceil(value); + } + return -floor(-value); + } + + /** + * Might have different semantics than StrictMath.round(float), + * see bugs 6430675 and 8010430. + * + * @param value A double value. + * @return Value rounded to nearest int, choosing superior int in case two + * are equally close (i.e. rounding-up). + */ + public static int round(float value) { + /* + * Not delegating to JDK, because we want delegation to provide + * at least as good results, and some supported JDK versions + * have bugged round() methods. + */ + // Algorithm by Dmitry Nadezhin (but replaced an if by a multiply) + // (http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-August/020247.html). + final int bits = Float.floatToRawIntBits(value); + final int biasedExp = ((bits>>23)&0xFF); + // Shift to get rid of bits past comma except first one: will need to + // 1-shift to the right to end up with correct magnitude. + final int shift = (23 - 1 + MAX_FLOAT_EXPONENT) - biasedExp; + if ((shift & -32) == 0) { + int bitsSignum = (((bits >> 31) << 1) + 1); + // shift in [0,31], so unbiased exp in [-9,22]. + int extendedMantissa = (0x00800000 | (bits & 0x007FFFFF)) * bitsSignum; + // If value is positive and first bit past comma is 0, rounding + // to lower integer, else to upper one, which is what "+1" and + // then ">>1" do. + return ((extendedMantissa >> shift) + 1) >> 1; + } else { + // +-Infinity, NaN, or a mathematical integer, or tiny. + if (false && ANTI_SLOW_CASTS) { // not worth it + if (Math.abs(value) >= -(float)Integer.MIN_VALUE) { + // +-Infinity or a mathematical integer (mostly) out of int range. + return (value < 0.0) ? Integer.MIN_VALUE : Integer.MAX_VALUE; + } + // NaN or a mathematical integer (mostly) in int range. + } + return (int)value; + } + } + + /** + * Might have different semantics than StrictMath.round(double), + * see bugs 6430675 and 8010430. + * + * @param value A double value. + * @return Value rounded to nearest long, choosing superior long in case two + * are equally close (i.e. rounding-up). + */ + public static long round(double value) { + /* + * Not delegating to JDK, because we want delegation to provide + * at least as good results, and some supported JDK versions + * have bugged round() methods. + */ + final long bits = Double.doubleToRawLongBits(value); + final int biasedExp = (((int)(bits>>52))&0x7FF); + // Shift to get rid of bits past comma except first one: will need to + // 1-shift to the right to end up with correct magnitude. + final int shift = (52 - 1 + MAX_DOUBLE_EXPONENT) - biasedExp; + if ((shift & -64) == 0) { + long bitsSignum = (((bits >> 63) << 1) + 1); + // shift in [0,63], so unbiased exp in [-12,51]. + long extendedMantissa = (0x0010000000000000L | (bits & 0x000FFFFFFFFFFFFFL)) * bitsSignum; + // If value is positive and first bit past comma is 0, rounding + // to lower integer, else to upper one, which is what "+1" and + // then ">>1" do. + return ((extendedMantissa >> shift) + 1L) >> 1; + } else { + // +-Infinity, NaN, or a mathematical integer, or tiny. + if (ANTI_SLOW_CASTS) { + if (Math.abs(value) >= -(double)Long.MIN_VALUE) { + // +-Infinity or a mathematical integer (mostly) out of long range. + return (value < 0.0) ? Long.MIN_VALUE : Long.MAX_VALUE; + } + // NaN or a mathematical integer (mostly) in long range. + } + return (long)value; + } + } + + /** + * @param value A float value. + * @return Value rounded to nearest int, choosing even int in case two + * are equally close. + */ + public static int roundEven(float value) { + final int sign = signFromBit(value); + value = Math.abs(value); + if (ANTI_SLOW_CASTS) { + if (value < TWO_POW_23_F) { + // Getting rid of post-comma bits. + value = ((value + TWO_POW_23_F) - TWO_POW_23_F); + return sign * (int)value; + } else if (value < (float)Integer.MAX_VALUE) { // "<=" doesn't work, because of float precision + // value is in [-Integer.MAX_VALUE,Integer.MAX_VALUE] + return sign * (int)value; + } + } else { + if (value < TWO_POW_23_F) { + // Getting rid of post-comma bits. + value = ((value + TWO_POW_23_F) - TWO_POW_23_F); + } + } + return (int)(sign * value); + } + + /** + * @param value A double value. + * @return Value rounded to nearest long, choosing even long in case two + * are equally close. + */ + public static long roundEven(double value) { + final int sign = (int)signFromBit(value); + value = Math.abs(value); + if (value < TWO_POW_52) { + // Getting rid of post-comma bits. + value = ((value + TWO_POW_52) - TWO_POW_52); + } + if (ANTI_SLOW_CASTS) { + if (value <= (double)Integer.MAX_VALUE) { + // value is in [-Integer.MAX_VALUE,Integer.MAX_VALUE] + return sign * (int)value; + } + } + return (long)(sign * value); + } + + /** + * @param value A float value. + * @return The float mathematical integer closest to the specified value, + * choosing even one if two are equally close, or respectively + * NaN, +-Infinity or +-0.0f if the value is any of these. + */ + public static float rint(float value) { + final int sign = signFromBit(value); + value = Math.abs(value); + if (value < TWO_POW_23_F) { + // Getting rid of post-comma bits. + value = ((TWO_POW_23_F + value ) - TWO_POW_23_F); + } + // Restoring original sign. + return sign * value; + } + + /** + * @param value A double value. + * @return The double mathematical integer closest to the specified value, + * choosing even one if two are equally close, or respectively + * NaN, +-Infinity or +-0.0 if the value is any of these. + */ + public static double rint(double value) { + if (USE_JDK_MATH) { + return StrictMath.rint(value); + } + final int sign = (int)signFromBit(value); + value = Math.abs(value); + if (value < TWO_POW_52) { + // Getting rid of post-comma bits. + value = ((TWO_POW_52 + value ) - TWO_POW_52); + } + // Restoring original sign. + return sign * value; + } + + /* + * close int values + * + * Never delegating to JDK for these methods, for we should always + * be faster and exact, and JDK doesn't exactly have such methods. + */ + + /** + * @param value A double value. + * @return Floor of value as int, or closest int if floor is out + * of int range, or 0 if value is NaN. + */ + public static int floorToInt(double value) { + int valueInt = (int) value; + if (value < 0.0) { + if (value == (double) valueInt) { + return valueInt; + } else { + if (valueInt == Integer.MIN_VALUE) { + return valueInt; + } else { + return valueInt - 1; + } + } + } else { // >= 0 or NaN. + return valueInt; + } + } + + /** + * @param value A double value. + * @return Ceiling of value as int, or closest int if ceiling is out + * of int range, or 0 if value is NaN. + */ + public static int ceilToInt(double value) { + int valueInt = (int) value; + if (value > 0.0) { + if (value == (double) valueInt) { + return valueInt; + } else { + if (valueInt == Integer.MAX_VALUE) { + return valueInt; + } else { + return valueInt + 1; + } + } + } else { // <= 0 or NaN. + return valueInt; + } + } + + /** + * @param value A double value. + * @return Value rounded to nearest int, choosing superior int in case two + * are equally close (i.e. rounding-up). + */ + public static int roundToInt(double value) { + /* + * We don't gain much by reimplementing rounding, except for + * pathologically large values, which should not be a common case + * when dealing with ints, so we just use round(double). + */ + return NumbersUtils.toInt(round(value)); + } + + /** + * @param value A double value. + * @return Value rounded to nearest int, choosing even int in case two + * are equally close. + */ + public static int roundEvenToInt(double value) { + final int sign = (int)signFromBit(value); + value = Math.abs(value); + /* + * Applying the post-comma bits removal logic even if value is out + * of int range, to avoid a test, for it doesn't mess up the result, + * and we want to optimize for the case of values in int range. + */ + value = ((value + TWO_POW_52) - TWO_POW_52); + return (int)(sign * value); + } + + /* + * ranges + */ + + /** + * @param min A float value. + * @param max A float value. + * @param value A float value. + * @return min if value < min, max if value > max, value otherwise. + */ + public static float toRange(float min, float max, float value) { + return NumbersUtils.toRange(min, max, value); + } + + /** + * @param min A double value. + * @param max A double value. + * @param value A double value. + * @return min if value < min, max if value > max, value otherwise. + */ + public static double toRange(double min, double max, double value) { + return NumbersUtils.toRange(min, max, value); + } + + /* + * binary operators (/,%) + */ + + /** + * Returns dividend - divisor * n, where n is the mathematical integer + * closest to dividend/divisor. + * If dividend/divisor is equally close to surrounding integers, + * we choose n to be the integer of smallest magnitude, which makes + * this treatment differ from StrictMath.IEEEremainder(double,double), + * where n is chosen to be the even integer. + * Note that the choice of n is not done considering the double + * approximation of dividend/divisor, because it could cause + * result to be outside [-|divisor|/2,|divisor|/2] range. + * The practical effect is that if multiple results would be possible, + * we always choose the result that is the closest to (and has the same + * sign as) the dividend. + * Ex. : + * - for (-3.0,2.0), this method returns -1.0, + * whereas StrictMath.IEEEremainder returns 1.0. + * - for (-5.0,2.0), both this method and StrictMath.IEEEremainder return -1.0. + * + * If the remainder is zero, its sign is the same as the sign of the first argument. + * If either argument is NaN, or the first argument is infinite, + * or the second argument is positive zero or negative zero, + * then the result is NaN. + * If the first argument is finite and the second argument is + * infinite, then the result is the same as the first argument. + * + * NB: + * - Modulo operator (%) returns a value in ]-|divisor|,|divisor|[, + * which sign is the same as dividend. + * - As for modulo operator, the sign of the divisor has no effect on the result. + * - On some architecture, % operator has been observed to return NaN + * for some subnormal values of divisor, when dividend exponent is 1023, + * which impacts the correctness of this method. + * + * @param dividend Dividend. + * @param divisor Divisor. + * @return Remainder of dividend/divisor, i.e. a value in [-|divisor|/2,|divisor|/2]. + */ + public static double remainder(double dividend, double divisor) { + if (Double.isInfinite(divisor)) { + if (Double.isInfinite(dividend)) { + return Double.NaN; + } else { + return dividend; + } + } + double value = dividend % divisor; + if (Math.abs(value+value) > Math.abs(divisor)) { + return value + ((value > 0.0) ? -Math.abs(divisor) : Math.abs(divisor)); + } else { + return value; + } + } + + /** + * @param angle Angle in radians. + * @return The same angle, in radians, but in [-PI,PI]. + */ + public static double normalizeMinusPiPi(double angle) { + // Not modifying values in output range. + if ((angle >= -Math.PI) && (angle <= Math.PI)) { + return angle; + } + return remainderTwoPi(angle); + } + + /** + * Not accurate for large values. + * + * @param angle Angle in radians. + * @return The same angle, in radians, but in [-PI,PI]. + */ + public static double normalizeMinusPiPiFast(double angle) { + // Not modifying values in output range. + if ((angle >= -Math.PI) && (angle <= Math.PI)) { + return angle; + } + return remainderTwoPiFast(angle); + } + + /** + * @param angle Angle in radians. + * @return The same angle, in radians, but in [0,2*PI]. + */ + public static double normalizeZeroTwoPi(double angle) { + // Not modifying values in output range. + if ((angle >= 0.0) && (angle <= 2*Math.PI)) { + return angle; + } + angle = remainderTwoPi(angle); + if (angle < 0.0) { + // LO then HI is theoretically better (when starting near 0). + return (angle + TWOPI_LO) + TWOPI_HI; + } else { + return angle; + } + } + + /** + * Not accurate for large values. + * + * @param angle Angle in radians. + * @return The same angle, in radians, but in [0,2*PI]. + */ + public static double normalizeZeroTwoPiFast(double angle) { + // Not modifying values in output range. + if ((angle >= 0.0) && (angle <= 2*Math.PI)) { + return angle; + } + angle = remainderTwoPiFast(angle); + if (angle < 0.0) { + // LO then HI is theoretically better (when starting near 0). + return (angle + TWOPI_LO) + TWOPI_HI; + } else { + return angle; + } + } + + /** + * @param angle Angle in radians. + * @return Angle value modulo PI, in radians, in [-PI/2,PI/2]. + */ + public static double normalizeMinusHalfPiHalfPi(double angle) { + // Not modifying values in output range. + if ((angle >= -Math.PI/2) && (angle <= Math.PI/2)) { + return angle; + } + return remainderPi(angle); + } + + /** + * Not accurate for large values. + * + * @param angle Angle in radians. + * @return Angle value modulo PI, in radians, in [-PI/2,PI/2]. + */ + public static double normalizeMinusHalfPiHalfPiFast(double angle) { + // Not modifying values in output range. + if ((angle >= -Math.PI/2) && (angle <= Math.PI/2)) { + return angle; + } + return remainderPiFast(angle); + } + + /* + * floating points utils + */ + + /** + * @param value A float value. + * @return true if the specified value is NaN or +-Infinity, false otherwise. + */ + public static boolean isNaNOrInfinite(float value) { + return NumbersUtils.isNaNOrInfinite(value); + } + + /** + * @param value A double value. + * @return true if the specified value is NaN or +-Infinity, false otherwise. + */ + public static boolean isNaNOrInfinite(double value) { + return NumbersUtils.isNaNOrInfinite(value); + } + + /** + * @param value A float value. + * @return Value unbiased exponent. + */ + public static int getExponent(float value) { + return ((Float.floatToRawIntBits(value)>>23)&0xFF)-MAX_FLOAT_EXPONENT; + } + + /** + * @param value A double value. + * @return Value unbiased exponent. + */ + public static int getExponent(double value) { + return (((int)(Double.doubleToRawLongBits(value)>>52))&0x7FF)-MAX_DOUBLE_EXPONENT; + } + + /** + * @param value A float value. + * @return -1.0f if the specified value is < 0, 1.0f if it is > 0, + * and the value itself if it is NaN or +-0.0f. + */ + public static float signum(float value) { + if (USE_JDK_MATH) { + return StrictMath.signum(value); + } + if ((value == 0.0f) || (value != value)) { + return value; + } + return (float)signFromBit(value); + } + + /** + * @param value A double value. + * @return -1.0 if the specified value is < 0, 1.0 if it is > 0, + * and the value itself if it is NaN or +-0.0. + */ + public static double signum(double value) { + if (USE_JDK_MATH) { + return StrictMath.signum(value); + } + if ((value == 0.0) || (value != value)) { + return value; + } + if (ANTI_SLOW_CASTS) { + return (double)(int)signFromBit(value); + } else { + return (double)signFromBit(value); + } + } + + /** + * @param value A float value. + * @return -1 if sign bit is 1, 1 if sign bit is 0. + */ + public static int signFromBit(float value) { + return ((Float.floatToRawIntBits(value)>>30)|1); + } + + /** + * @param value A double value. + * @return -1 if sign bit is 1, 1 if sign bit is 0. + */ + public static long signFromBit(double value) { + // Returning a long, to avoid useless cast into int. + return ((Double.doubleToRawLongBits(value)>>62)|1); + } + + /** + * A sign of NaN is interpreted as positive. + * + * @param magnitude A float value. + * @param sign A float value. + * @return A value with the magnitude of the first argument, and the sign + * of the second argument. + */ + public static float copySign(float magnitude, float sign) { + return Float.intBitsToFloat( + (Float.floatToRawIntBits((sign != sign) ? 1.0f : sign) & Integer.MIN_VALUE) + | (Float.floatToRawIntBits(magnitude) & Integer.MAX_VALUE)); + } + + /** + * A sign of NaN is interpreted as positive. + * + * @param magnitude A double value. + * @param sign A double value. + * @return A value with the magnitude of the first argument, and the sign + * of the second argument. + */ + public static double copySign(double magnitude, double sign) { + return Double.longBitsToDouble( + (Double.doubleToRawLongBits((sign != sign) ? 1.0 : sign) & Long.MIN_VALUE) + | (Double.doubleToRawLongBits(magnitude) & Long.MAX_VALUE)); + } + + /** + * The ULP (Unit in the Last Place) is the distance to the next value larger + * in magnitude. + * + * @param value A float value. + * @return The size of an ulp of the specified value, or Float.MIN_VALUE + * if it is +-0.0f, or +Infinity if it is +-Infinity, or NaN + * if it is NaN. + */ + public static float ulp(float value) { + if (USE_JDK_MATH) { + return StrictMath.ulp(value); + } + /* + * Look-up table not really worth it in micro-benchmark, + * so should be worse with cache-misses. + */ + final int exponent = getExponent(value); + if (exponent >= (MIN_FLOAT_NORMAL_EXPONENT+23)) { + if (exponent == MAX_FLOAT_EXPONENT+1) { + // NaN or +-Infinity + return Math.abs(value); + } + // normal: returning 2^(exponent-23) + return Float.intBitsToFloat((exponent+(MAX_FLOAT_EXPONENT-23))<<23); + } else { + if (exponent == MIN_FLOAT_NORMAL_EXPONENT-1) { + // +-0.0f or subnormal + return Float.MIN_VALUE; + } + // subnormal result + return Float.intBitsToFloat(1<<(exponent-MIN_FLOAT_NORMAL_EXPONENT)); + } + } + + /** + * The ULP (Unit in the Last Place) is the distance to the next value larger + * in magnitude. + * + * @param value A double value. + * @return The size of an ulp of the specified value, or Double.MIN_VALUE + * if it is +-0.0, or +Infinity if it is +-Infinity, or NaN + * if it is NaN. + */ + public static double ulp(double value) { + if (USE_JDK_MATH) { + return StrictMath.ulp(value); + } + /* + * Look-up table not really worth it in micro-benchmark, + * so should be worse with cache-misses. + */ + final int exponent = getExponent(value); + if (exponent >= (MIN_DOUBLE_NORMAL_EXPONENT+52)) { + if (exponent == MAX_DOUBLE_EXPONENT+1) { + // NaN or +-Infinity + return Math.abs(value); + } + // normal: returning 2^(exponent-52) + return Double.longBitsToDouble((exponent+(MAX_DOUBLE_EXPONENT-52L))<<52); + } else { + if (exponent == MIN_DOUBLE_NORMAL_EXPONENT-1) { + // +-0.0f or subnormal + return Double.MIN_VALUE; + } + // subnormal result + return Double.longBitsToDouble(1L<<(exponent-MIN_DOUBLE_NORMAL_EXPONENT)); + } + } + + /** + * If both arguments are +-0.0(f), (float)direction is returned. + * + * If both arguments are +Infinity or -Infinity, + * respectively +Infinity or -Infinity is returned. + * + * @param start A float value. + * @param direction A double value. + * @return The float adjacent to start towards direction, considering that + * +(-)Float.MIN_VALUE is adjacent to +(-)0.0f, and that + * +(-)Float.MAX_VALUE is adjacent to +(-)Infinity, + * or NaN if any argument is NaN. + */ + public static float nextAfter(float start, double direction) { + if (direction < start) { + // Going towards -Infinity. + if (start == 0.0f) { + // +-0.0f + return -Float.MIN_VALUE; + } + final int bits = Float.floatToRawIntBits(start); + return Float.intBitsToFloat(bits + ((bits > 0) ? -1 : 1)); + } else if (direction > start) { + // Going towards +Infinity. + // +0.0f to get rid of eventual -0.0f + final int bits = Float.floatToRawIntBits(start + 0.0f); + return Float.intBitsToFloat(bits + (bits >= 0 ? 1 : -1)); + } else if (start == direction) { + return (float)direction; + } else { + // Returning a NaN derived from the input NaN(s). + return start + (float)direction; + } + } + + /** + * If both arguments are +-0.0, direction is returned. + * + * If both arguments are +Infinity or -Infinity, + * respectively +Infinity or -Infinity is returned. + * + * @param start A double value. + * @param direction A double value. + * @return The double adjacent to start towards direction, considering that + * +(-)Double.MIN_VALUE is adjacent to +(-)0.0, and that + * +(-)Double.MAX_VALUE is adjacent to +(-)Infinity, + * or NaN if any argument is NaN. + */ + public static double nextAfter(double start, double direction) { + if (direction < start) { + // Going towards -Infinity. + if (start == 0.0) { + // +-0.0 + return -Double.MIN_VALUE; + } + final long bits = Double.doubleToRawLongBits(start); + return Double.longBitsToDouble(bits + ((bits > 0) ? -1 : 1)); + } else if (direction > start) { + // Going towards +Infinity. + // +0.0 to get rid of eventual -0.0 + final long bits = Double.doubleToRawLongBits(start + 0.0f); + return Double.longBitsToDouble(bits + (bits >= 0 ? 1 : -1)); + } else if (start == direction) { + return direction; + } else { + // Returning a NaN derived from the input NaN(s). + return start + direction; + } + } + + /** + * Semantically equivalent to nextAfter(start,Double.NEGATIVE_INFINITY). + */ + public static float nextDown(float start) { + if (start > Float.NEGATIVE_INFINITY) { + if (start == 0.0f) { + // +-0.0f + return -Float.MIN_VALUE; + } + final int bits = Float.floatToRawIntBits(start); + return Float.intBitsToFloat(bits + ((bits > 0) ? -1 : 1)); + } else if (start == Float.NEGATIVE_INFINITY) { + return Float.NEGATIVE_INFINITY; + } else { + // NaN + return start; + } + } + + /** + * Semantically equivalent to nextAfter(start,Double.NEGATIVE_INFINITY). + */ + public static double nextDown(double start) { + if (start > Double.NEGATIVE_INFINITY) { + if (start == 0.0) { + // +-0.0 + return -Double.MIN_VALUE; + } + final long bits = Double.doubleToRawLongBits(start); + return Double.longBitsToDouble(bits + ((bits > 0) ? -1 : 1)); + } else if (start == Double.NEGATIVE_INFINITY) { + return Double.NEGATIVE_INFINITY; + } else { + // NaN + return start; + } + } + + /** + * Semantically equivalent to nextAfter(start,Double.POSITIVE_INFINITY). + */ + public static float nextUp(float start) { + if (start < Float.POSITIVE_INFINITY) { + // +0.0f to get rid of eventual -0.0f + final int bits = Float.floatToRawIntBits(start + 0.0f); + return Float.intBitsToFloat(bits + (bits >= 0 ? 1 : -1)); + } else if (start == Float.POSITIVE_INFINITY) { + return Float.POSITIVE_INFINITY; + } else { + // NaN + return start; + } + } + + /** + * Semantically equivalent to nextAfter(start,Double.POSITIVE_INFINITY). + */ + public static double nextUp(double start) { + if (start < Double.POSITIVE_INFINITY) { + // +0.0 to get rid of eventual -0.0 + final long bits = Double.doubleToRawLongBits(start + 0.0); + return Double.longBitsToDouble(bits + (bits >= 0 ? 1 : -1)); + } else if (start == Double.POSITIVE_INFINITY) { + return Double.POSITIVE_INFINITY; + } else { + // NaN + return start; + } + } + + /** + * Precision may be lost if the result is subnormal. + * + * @param value A float value. + * @param scaleFactor An int value. + * @return value * 2^scaleFactor, or a value equivalent to the specified + * one if it is NaN, +-Infinity or +-0.0f. + */ + public static float scalb(float value, int scaleFactor) { + // Large enough to imply overflow or underflow for + // a finite non-zero value. + final int MAX_SCALE = 2*MAX_FLOAT_EXPONENT+23+1; + + // Making sure scaling factor is in a reasonable range. + scaleFactor = Math.max(Math.min(scaleFactor, MAX_SCALE), -MAX_SCALE); + + return (float)(((double)value) * twoPowNormal(scaleFactor)); + } + + /** + * Precision may be lost if the result is subnormal. + * + * @param value A double value. + * @param scaleFactor An int value. + * @return value * 2^scaleFactor, or a value equivalent to the specified + * one if it is NaN, +-Infinity or +-0.0. + */ + public static double scalb(double value, int scaleFactor) { + if ((scaleFactor > -MAX_DOUBLE_EXPONENT) && (scaleFactor <= MAX_DOUBLE_EXPONENT)) { + // Quick case (as done in apache FastMath). + return value * twoPowNormal(scaleFactor); + } + + // Large enough to imply overflow or underflow for + // a finite non-zero value. + final int MAX_SCALE = 2*MAX_DOUBLE_EXPONENT+52+1; + + // Making sure scaling factor is in a reasonable range. + final int exponentAdjust; + final int scaleIncrement; + final double exponentDelta; + if (scaleFactor < 0) { + scaleFactor = Math.max(scaleFactor, -MAX_SCALE); + scaleIncrement = -512; + exponentDelta = TWO_POW_N512; + } else { + scaleFactor = Math.min(scaleFactor, MAX_SCALE); + scaleIncrement = 512; + exponentDelta = TWO_POW_512; + } + + // Calculating (scaleFactor % +-512), 512 = 2^9, using + // technique from "Hacker's Delight" section 10-2. + final int t = ((scaleFactor >> (9-1)) >>> (32-9)); + exponentAdjust = ((scaleFactor + t) & (512-1)) - t; + + value *= twoPowNormal(exponentAdjust); + scaleFactor -= exponentAdjust; + + while (scaleFactor != 0) { + value *= exponentDelta; + scaleFactor -= scaleIncrement; + } + + return value; + } + + /* + * Non-redefined StrictMath public values and treatments. + */ + + public static float abs(float a) { + return StrictMath.abs(a); + } + + public static double abs(double a) { + return StrictMath.abs(a); + } + + public static float min(float a, float b) { + return StrictMath.min(a,b); + } + + public static double min(double a, double b) { + return StrictMath.min(a,b); + } + + public static float max(float a, float b) { + return StrictMath.max(a,b); + } + + public static double max(double a, double b) { + return StrictMath.max(a,b); + } + + public static double IEEEremainder(double f1, double f2) { + return StrictMath.IEEEremainder(f1,f2); + } + + public static double random() { + return StrictMath.random(); + } + + //-------------------------------------------------------------------------- + // PRIVATE METHODS + //-------------------------------------------------------------------------- + + /** + * Non-instantiable. + */ + private StrictFastMath() { + } + + /* + * Remainders (accurate). + */ + + /** + * @param angle Angle in radians. + * @return Remainder of (angle % (2*PI)), in [-PI,PI]. + */ + private static double remainderTwoPi(double angle) { + if (USE_JDK_MATH) { + return jdkRemainderTwoPi(angle); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + if (angle <= (4*NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2)) { + double fn = (double)(int)(angle*TWOPI_INV+0.5); + angle = (angle - fn*TWOPI_HI) - fn*TWOPI_LO; + // Ensuring range. + // HI/LO can help a bit, even though we are always far from 0. + if (angle < -Math.PI) { + angle = (angle + TWOPI_HI) + TWOPI_LO; + } else if (angle > Math.PI) { + angle = (angle - TWOPI_HI) - TWOPI_LO; + } + return negateResult ? -angle : angle; + } else if (angle < Double.POSITIVE_INFINITY) { + angle = heavyRemainderTwoPi(angle); + return negateResult ? -angle : angle; + } else { // angle is +Infinity or NaN + return Double.NaN; + } + } + + /** + * @param angle Angle in radians. + * @return Remainder of (angle % PI), in [-PI/2,PI/2]. + */ + private static double remainderPi(double angle) { + if (USE_JDK_MATH) { + return jdkRemainderPi(angle); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + if (angle <= (2*NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2)) { + double fn = (double)(int)(angle*PI_INV+0.5); + angle = (angle - fn*PI_HI) - fn*PI_LO; + // Ensuring range. + // HI/LO can help a bit, even though we are always far from 0. + if (angle < -Math.PI/2) { + angle = (angle + PI_HI) + PI_LO; + } else if (angle > Math.PI/2) { + angle = (angle - PI_HI) - PI_LO; + } + return negateResult ? -angle : angle; + } else if (angle < Double.POSITIVE_INFINITY) { + angle = heavyRemainderPi(angle); + return negateResult ? -angle : angle; + } else { // angle is +Infinity or NaN + return Double.NaN; + } + } + + /** + * @param angle Angle in radians. + * @return Bits of double corresponding to remainder of (angle % (PI/2)), + * in [-PI/4,PI/4], with quadrant encoded in exponent bits. + */ + private static long remainderPiO2(double angle) { + if (USE_JDK_MATH) { + return jdkRemainderPiO2(angle, false); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + if (angle <= NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2) { + int n = (int)(angle*PIO2_INV+0.5); + double fn = (double)n; + angle = (angle - fn*PIO2_HI) - fn*PIO2_LO; + // Ensuring range. + // HI/LO can help a bit, even though we are always far from 0. + if (angle < -Math.PI/4) { + angle = (angle + PIO2_HI) + PIO2_LO; + n--; + } else if (angle > Math.PI/4) { + angle = (angle - PIO2_HI) - PIO2_LO; + n++; + } + if (negateResult) { + angle = -angle; + } + return encodeRemainderAndQuadrant(angle, n&3); + } else if (angle < Double.POSITIVE_INFINITY) { + return heavyRemainderPiO2(angle, negateResult); + } else { // angle is +Infinity or NaN + return encodeRemainderAndQuadrant(Double.NaN, 0); + } + } + + /* + * Remainders (fast). + */ + + /** + * Not accurate for large values. + * + * @param angle Angle in radians. + * @return Remainder of (angle % (2*PI)), in [-PI,PI]. + */ + private static double remainderTwoPiFast(double angle) { + if (USE_JDK_MATH) { + return jdkRemainderTwoPi(angle); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + // - We don't bother with values higher than (2*PI*(2^52)), + // since they are spaced by 2*PI or more from each other. + // - For large values, we don't use % because it might be very slow, + // and we split computation in two, because cast from double to int + // with large numbers might be very slow also. + if (angle <= TWO_POW_26*(2*Math.PI)) { + // ok + } else if (angle <= TWO_POW_52*(2*Math.PI)) { + // Computing remainder of angle modulo TWO_POW_26*(2*PI). + double fn = (double)(int)(angle*(TWOPI_INV/TWO_POW_26)+0.5); + angle = (angle - fn*(TWOPI_HI*TWO_POW_26)) - fn*(TWOPI_LO*TWO_POW_26); + // Here, angle is in [-TWO_POW_26*PI,TWO_POW_26*PI], or so. + if (angle < 0.0) { + angle = -angle; + negateResult = !negateResult; + } + } else if (angle < Double.POSITIVE_INFINITY) { + return 0.0; + } else { // angle is +Infinity or NaN + return Double.NaN; + } + + // Computing remainder of angle modulo 2*PI. + double fn = (double)(int)(angle*TWOPI_INV+0.5); + angle = (angle - fn*TWOPI_HI) - fn*TWOPI_LO; + + // Ensuring range. + // HI/LO can help a bit, even though we are always far from 0. + if (angle < -Math.PI) { + angle = (angle + TWOPI_HI) + TWOPI_LO; + } else if (angle > Math.PI) { + angle = (angle - TWOPI_HI) - TWOPI_LO; + } + return negateResult ? -angle : angle; + } + + /** + * Not accurate for large values. + * + * @param angle Angle in radians. + * @return Remainder of (angle % PI), in [-PI/2,PI/2]. + */ + private static double remainderPiFast(double angle) { + if (USE_JDK_MATH) { + return jdkRemainderPi(angle); + } + boolean negateResult = false; + if (angle < 0.0) { + angle = -angle; + negateResult = true; + } + // - We don't bother with values higher than (PI*(2^52)), + // since they are spaced by PI or more from each other. + // - For large values, we don't use % because it might be very slow, + // and we split computation in two, because cast from double to int + // with large numbers might be very slow also. + if (angle <= TWO_POW_26*Math.PI) { + // ok + } else if (angle <= TWO_POW_52*Math.PI) { + // Computing remainder of angle modulo TWO_POW_26*PI. + double fn = (double)(int)(angle*(PI_INV/TWO_POW_26)+0.5); + angle = (angle - fn*(PI_HI*TWO_POW_26)) - fn*(PI_LO*TWO_POW_26); + // Here, angle is in [-TWO_POW_26*PI/2,TWO_POW_26*PI/2], or so. + if (angle < 0.0) { + angle = -angle; + negateResult = !negateResult; + } + } else if (angle < Double.POSITIVE_INFINITY) { + return 0.0; + } else { // angle is +Infinity or NaN + return Double.NaN; + } + + // Computing remainder of angle modulo PI. + double fn = (double)(int)(angle*PI_INV+0.5); + angle = (angle - fn*PI_HI) - fn*PI_LO; + + // Ensuring range. + // HI/LO can help a bit, even though we are always far from 0. + if (angle < -Math.PI/2) { + angle = (angle + PI_HI) + PI_LO; + } else if (angle > Math.PI/2) { + angle = (angle - PI_HI) - PI_LO; + } + return negateResult ? -angle : angle; + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 661afa67c..15a6a176c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -43,6 +43,7 @@ include( ":kmath-tensors", ":kmath-jupyter", ":kmath-symja", + ":kmath-jafama", ":examples", ":benchmarks" ) From 6c815abd54a248cd1f95e02d580382e4b55377ba Mon Sep 17 00:00:00 2001 From: therealansh Date: Thu, 3 Jun 2021 01:37:23 +0530 Subject: [PATCH 381/393] chore: refactored and dependency add --- kmath-jafama/build.gradle.kts | 9 +- .../kscience/kmath/jafama/CmnFastMath.java | 2112 ------------ .../kscience/kmath/jafama/DoubleWrapper.java | 13 - .../space/kscience/kmath/jafama/FastMath.java | 2986 ---------------- .../kscience/kmath/jafama/IntWrapper.java | 13 - .../kscience/kmath/jafama/KMathJafama.kt | 3 +- .../kscience/kmath/jafama/NumbersUtils.java | 2647 --------------- .../kscience/kmath/jafama/StrictFastMath.java | 2998 ----------------- 8 files changed, 6 insertions(+), 10775 deletions(-) delete mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/CmnFastMath.java delete mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/DoubleWrapper.java delete mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/FastMath.java delete mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/IntWrapper.java delete mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/NumbersUtils.java delete mode 100644 kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/StrictFastMath.java diff --git a/kmath-jafama/build.gradle.kts b/kmath-jafama/build.gradle.kts index 22d50f89c..f31f2602f 100644 --- a/kmath-jafama/build.gradle.kts +++ b/kmath-jafama/build.gradle.kts @@ -3,13 +3,12 @@ plugins { } dependencies { - api(project(":kmath-ast")) - api(project(":kmath-complex")) - api(project(":kmath-for-real")) + api(project(":kmath-core")) + api("net.jafama:jafama:2.3.2") } -kscience{ - useHtml() +repositories { + mavenCentral() } readme { diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/CmnFastMath.java b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/CmnFastMath.java deleted file mode 100644 index 0abc5d95d..000000000 --- a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/CmnFastMath.java +++ /dev/null @@ -1,2112 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.jafama; - -/** - * Stuffs for FastMath and StrictFastMath. - */ -abstract class CmnFastMath { - - /* - * For trigonometric functions, use of look-up tables and Taylor-Lagrange formula - * with 4 derivatives (more take longer to compute and don't add much accuracy, - * less require larger tables (which use more memory, take more time to initialize, - * and are slower to access (at least on the machine they were developed on))). - * - * For angles reduction of cos/sin/tan functions: - * - for small values, instead of reducing angles, and then computing the best index - * for look-up tables, we compute this index right away, and use it for reduction, - * - for large values, treatments derived from fdlibm package are used, as done in - * java.lang.Math. They are faster but still "slow", so if you work with - * large numbers and need speed over accuracy for them, you might want to use - * normalizeXXXFast treatments before your function, or modify cos/sin/tan - * so that they call the fast normalization treatments instead of the accurate ones. - * NB: If an angle is huge (like PI*1e20), in double precision format its last digits - * are zeros, which most likely is not the case for the intended value, and doing - * an accurate reduction on a very inaccurate value is most likely pointless. - * But it gives some sort of coherence that could be needed in some cases. - * - * Multiplication on double appears to be about as fast (or not much slower) than call - * to [], and regrouping some doubles in a private class, to use - * index only once, does not seem to speed things up, so: - * - for uniformly tabulated values, to retrieve the parameter corresponding to - * an index, we recompute it rather than using an array to store it, - * - for cos/sin, we recompute derivatives divided by (multiplied by inverse of) - * factorial each time, rather than storing them in arrays. - * - * Lengths of look-up tables are usually of the form 2^n+1, for their values to be - * of the form ( * k/2^n, k in 0 .. 2^n), so that particular values - * (PI/2, etc.) are "exactly" computed, as well as for other reasons. - * - * Tables are put in specific inner classes, to be lazily initialized. - * Always doing strict tables initialization, even if StrictFastMath delegates - * to StrictMath and doesn't use tables, which makes tables initialization a bit - * slower but code simpler. - * Using redefined pure Java treatments during tables initialization, - * instead of Math or StrictMath ones (even asin(double)), can be very slow, - * because class loading is likely not to be optimized. - * - * Most math treatments I could find on the web, including "fast" ones, - * usually take care of special cases (NaN, etc.) at the beginning, and - * then deal with the general case, which adds a useless overhead for the - * general (and common) case. In this class, special cases are only dealt - * with when needed, and if the general case does not already handle them. - */ - - /* - * Regarding strictfp-ness: - * - * Switching from/to strictfp has some overhead, so we try to only - * strictfp-ize when needed (or when clueless). - * Compile-time constants are computed in a FP-strict way, so no need - * to make this whole class strictfp. - */ - - //-------------------------------------------------------------------------- - // CONFIGURATION - //-------------------------------------------------------------------------- - - /* - * FastMath - */ - - static final boolean FM_USE_JDK_MATH = getBooleanProperty("jafama.usejdk", false); - - /** - * Used for both FastMath.log(double) and FastMath.log10(double). - */ - static final boolean FM_USE_REDEFINED_LOG = getBooleanProperty("jafama.fastlog", false); - - static final boolean FM_USE_REDEFINED_SQRT = getBooleanProperty("jafama.fastsqrt", false); - - /** - * Set it to true if FastMath.sqrt(double) is slow - * (more tables, but less calls to FastMath.sqrt(double)). - */ - static final boolean FM_USE_POWTABS_FOR_ASIN = false; - - /* - * StrictFastMath - */ - - static final boolean SFM_USE_JDK_MATH = getBooleanProperty("jafama.strict.usejdk", false); - - /** - * Used for both StrictFastMath.log(double) and StrictFastMath.log10(double). - * True by default because the StrictMath implementations can be slow. - */ - static final boolean SFM_USE_REDEFINED_LOG = getBooleanProperty("jafama.strict.fastlog", true); - - static final boolean SFM_USE_REDEFINED_SQRT = getBooleanProperty("jafama.strict.fastsqrt", false); - - /** - * Set it to true if StrictFastMath.sqrt(double) is slow - * (more tables, but less calls to StrictFastMath.sqrt(double)). - */ - static final boolean SFM_USE_POWTABS_FOR_ASIN = false; - - /* - * Common to FastMath and StrictFastMath. - */ - - /** - * Using two pow tab can just make things barely faster, - * and could relatively hurt in case of cache-misses, - * especially for methods that otherwise wouldn't rely - * on any tab, so we don't use it. - */ - static final boolean USE_TWO_POW_TAB = false; - - /** - * Because on some architectures, some casts can be slow, - * especially for large values. - * Might make things a bit slower for latest architectures, - * but not as much as it makes them faster for older ones. - */ - static final boolean ANTI_SLOW_CASTS = true; - - /** - * If some methods get JIT-optimized, they might crash - * if they contain "(var == xxx)" with var being NaN - * (can happen with Java 6u29). - * - * The crash does not happen if we replace "==" with "<" or ">". - * - * Only the code that has been observed to trigger the bug - * has been modified. - */ - static final boolean ANTI_JIT_OPTIM_CRASH_ON_NAN = true; - - //-------------------------------------------------------------------------- - // GENERAL CONSTANTS - //-------------------------------------------------------------------------- - - /** - * Closest double approximation of e. - */ - public static final double E = Math.E; - - /** - * Closest double approximation of pi, which is inferior to mathematical pi: - * pi ~= 3.14159265358979323846... - * PI ~= 3.141592653589793 - */ - public static final double PI = Math.PI; - - /** - * High double approximation of pi, which is further from pi - * than the low approximation PI: - * pi ~= 3.14159265358979323846... - * PI ~= 3.141592653589793 - * PI_SUP ~= 3.1415926535897936 - */ - public static final double PI_SUP = Double.longBitsToDouble(Double.doubleToRawLongBits(Math.PI)+1); - - static final double ONE_DIV_F2 = 1/2.0; - static final double ONE_DIV_F3 = 1/6.0; - static final double ONE_DIV_F4 = 1/24.0; - - static final float TWO_POW_23_F = (float)NumbersUtils.twoPow(23); - - static final double TWO_POW_24 = NumbersUtils.twoPow(24); - private static final double TWO_POW_N24 = NumbersUtils.twoPow(-24); - - static final double TWO_POW_26 = NumbersUtils.twoPow(26); - static final double TWO_POW_N26 = NumbersUtils.twoPow(-26); - - // First double value (from zero) such as (value+-1/value == value). - static final double TWO_POW_27 = NumbersUtils.twoPow(27); - static final double TWO_POW_N27 = NumbersUtils.twoPow(-27); - - static final double TWO_POW_N28 = NumbersUtils.twoPow(-28); - - static final double TWO_POW_52 = NumbersUtils.twoPow(52); - - static final double TWO_POW_N55 = NumbersUtils.twoPow(-55); - - static final double TWO_POW_66 = NumbersUtils.twoPow(66); - - static final double TWO_POW_512 = NumbersUtils.twoPow(512); - static final double TWO_POW_N512 = NumbersUtils.twoPow(-512); - - /** - * Double.MIN_NORMAL since Java 6. - */ - static final double DOUBLE_MIN_NORMAL = Double.longBitsToDouble(0x0010000000000000L); // 2.2250738585072014E-308 - - // Not storing float/double mantissa size in constants, - // for 23 and 52 are shorter to read and more - // bitwise-explicit than some constant's name. - - static final int MIN_DOUBLE_EXPONENT = -1074; - static final int MIN_DOUBLE_NORMAL_EXPONENT = -1022; - static final int MAX_DOUBLE_EXPONENT = 1023; - - static final int MIN_FLOAT_NORMAL_EXPONENT = -126; - static final int MAX_FLOAT_EXPONENT = 127; - - private static final double SQRT_2 = StrictMath.sqrt(2.0); - - static final double LOG_2 = StrictMath.log(2.0); - static final double LOG_TWO_POW_27 = StrictMath.log(TWO_POW_27); - static final double LOG_DOUBLE_MAX_VALUE = StrictMath.log(Double.MAX_VALUE); - - static final double INV_LOG_10 = 1.0/StrictMath.log(10.0); - - static final double DOUBLE_BEFORE_60 = Double.longBitsToDouble(Double.doubleToRawLongBits(60.0)-1); - - //-------------------------------------------------------------------------- - // CONSTANTS FOR NORMALIZATIONS - //-------------------------------------------------------------------------- - - /** - * Table of constants for 1/(PI/2), 282 Hex digits (enough for normalizing doubles). - * 1/(PI/2) approximation = sum of TWO_OVER_PI_TAB[i]*2^(-24*(i+1)). - * - * double and not int, to avoid int-to-double cast during computations. - */ - private static final double TWO_OVER_PI_TAB[] = { - 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, - 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, - 0x424DD2, 0xe00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, - 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, - 0x3991d6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, - 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, - 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, - 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, - 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, - 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, - 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B}; - - /* - * Constants for PI/2. Only the 23 most significant bits of each mantissa are used. - * 2*PI approximation = sum of TWOPI_TAB. - */ - private static final double PIO2_TAB0 = Double.longBitsToDouble(0x3FF921FB40000000L); - private static final double PIO2_TAB1 = Double.longBitsToDouble(0x3E74442D00000000L); - private static final double PIO2_TAB2 = Double.longBitsToDouble(0x3CF8469880000000L); - private static final double PIO2_TAB3 = Double.longBitsToDouble(0x3B78CC5160000000L); - private static final double PIO2_TAB4 = Double.longBitsToDouble(0x39F01B8380000000L); - private static final double PIO2_TAB5 = Double.longBitsToDouble(0x387A252040000000L); - - static final double PIO2_INV = Double.longBitsToDouble(0x3FE45F306DC9C883L); // 6.36619772367581382433e-01 53 bits of 2/pi - static final double PIO2_HI = Double.longBitsToDouble(0x3FF921FB54400000L); // 1.57079632673412561417e+00 first 33 bits of pi/2 - static final double PIO2_LO = Double.longBitsToDouble(0x3DD0B4611A626331L); // 6.07710050650619224932e-11 pi/2 - PIO2_HI - static final double PI_INV = PIO2_INV/2; - static final double PI_HI = 2*PIO2_HI; - static final double PI_LO = 2*PIO2_LO; - static final double TWOPI_INV = PIO2_INV/4; - static final double TWOPI_HI = 4*PIO2_HI; - static final double TWOPI_LO = 4*PIO2_LO; - - /** - * Bit = 0 where quadrant is encoded in remainder bits. - */ - private static final long QUADRANT_BITS_0_MASK = 0xCFFFFFFFFFFFFFFFL; - - /** - * Remainder bits where quadrant is encoded, 0 elsewhere. - */ - private static final long QUADRANT_PLACE_BITS = 0x3000000000000000L; - - /** - * fdlibm uses 2^19*PI/2 here. - * With 2^18*PI/2 we would be more accurate, for example when normalizing - * 822245.903631403, which is close to 2^19*PI/2, but we are still in - * our accuracy tolerance with fdlibm's value (but not 2^20*PI/2) so we - * stick to it, to help being faster than (Strict)Math for values in - * [2^18*PI/2,2^19*PI/2]. - * - * For tests, can use a smaller value, for heavy remainder - * not to only be used with huge values. - */ - static final double NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2 = StrictMath.pow(2.0,19.0)*(Math.PI/2); - - /** - * 2*Math.PI, normalized into [-PI,PI], as returned by - * StrictMath.asin(StrictMath.sin(2*Math.PI)) - * (asin behaves as identity for this). - * - * NB: NumbersUtils.minus2PI(2*Math.PI) returns -2.449293598153844E-16, - * which is different due to not using an accurate enough definition of PI. - */ - static final double TWO_MATH_PI_IN_MINUS_PI_PI = -2.4492935982947064E-16; - - //-------------------------------------------------------------------------- - // CONSTANTS AND TABLES FOR SIN AND COS - //-------------------------------------------------------------------------- - - static final int SIN_COS_TABS_SIZE = (1<>9) / SIN_COS_INDEXER) * 0.99; - - //-------------------------------------------------------------------------- - // CONSTANTS AND TABLES FOR TAN - //-------------------------------------------------------------------------- - - // We use the following formula: - // 1) tan(-x) = -tan(x) - // 2) tan(x) = 1/tan(PI/2-x) - // ---> we only have to compute tan(x) on [0,A] with PI/4<=A= 45deg, and supposed to be >= 51.4deg, as fdlibm code is not - * supposed to work with values inferior to that (51.4deg is about - * (PI/2-Double.longBitsToDouble(0x3FE5942800000000L))). - */ - static final double TAN_MAX_VALUE_FOR_TABS = StrictMath.toRadians(77.0); - - static final int TAN_TABS_SIZE = (int)((TAN_MAX_VALUE_FOR_TABS/(Math.PI/2)) * (TAN_VIRTUAL_TABS_SIZE-1)) + 1; - static final double TAN_DELTA_HI = PIO2_HI/(TAN_VIRTUAL_TABS_SIZE-1); - static final double TAN_DELTA_LO = PIO2_LO/(TAN_VIRTUAL_TABS_SIZE-1); - static final double TAN_INDEXER = 1/(TAN_DELTA_HI+TAN_DELTA_LO); - - static final class MyTTan { - static final double[] tanTab = new double[TAN_TABS_SIZE]; - static final double[] tanDer1DivF1Tab = new double[TAN_TABS_SIZE]; - static final double[] tanDer2DivF2Tab = new double[TAN_TABS_SIZE]; - static final double[] tanDer3DivF3Tab = new double[TAN_TABS_SIZE]; - static final double[] tanDer4DivF4Tab = new double[TAN_TABS_SIZE]; - static { - init(); - } - private static strictfp void init() { - for (int i=0;i>9) / TAN_INDEXER) * 0.99); - - //-------------------------------------------------------------------------- - // CONSTANTS AND TABLES FOR ACOS, ASIN - //-------------------------------------------------------------------------- - - // We use the following formula: - // 1) acos(x) = PI/2 - asin(x) - // 2) asin(-x) = -asin(x) - // ---> we only have to compute asin(x) on [0,1]. - // For values not close to +-1, we use look-up tables; - // for values near +-1, we use code derived from fdlibm. - - /** - * Supposed to be >= sin(77.2deg), as fdlibm code is supposed to work with values > 0.975, - * but seems to work well enough as long as value >= sin(25deg). - */ - static final double ASIN_MAX_VALUE_FOR_TABS = StrictMath.sin(StrictMath.toRadians(73.0)); - - static final int ASIN_TABS_SIZE = (1< we only have to compute atan(x) on [0,+Infinity[. - // For values corresponding to angles not close to +-PI/2, we use look-up tables; - // for values corresponding to angles near +-PI/2, we use code derived from fdlibm. - - /** - * Supposed to be >= tan(67.7deg), as fdlibm code is supposed to work with values > 2.4375. - */ - static final double ATAN_MAX_VALUE_FOR_TABS = StrictMath.tan(StrictMath.toRadians(74.0)); - - static final int ATAN_TABS_SIZE = (1<>SQRT_LO_BITS)); - for (int i=1;i>CBRT_LO_BITS)); - for (int i=1;i= MIN_DOUBLE_EXPONENT) { - if (power <= MAX_DOUBLE_EXPONENT) { // Normal or subnormal. - return MyTTwoPow.twoPowTab[power-MIN_DOUBLE_EXPONENT]; - } else { // Overflow. - return Double.POSITIVE_INFINITY; - } - } else { // Underflow. - return 0.0; - } - } else { - return NumbersUtils.twoPow(power); - } - } - - /** - * @param value An int value. - * @return value*value. - */ - public static int pow2(int value) { - return value*value; - } - - /** - * @param value A long value. - * @return value*value. - */ - public static long pow2(long value) { - return value*value; - } - - /** - * @param value An int value. - * @return value*value*value. - */ - public static int pow3(int value) { - return value*value*value; - } - - /** - * @param value A long value. - * @return value*value*value. - */ - public static long pow3(long value) { - return value*value*value; - } - - /* - * absolute values - */ - - /** - * @param value An int value. - * @return The absolute value, except if value is Integer.MIN_VALUE, for which it returns Integer.MIN_VALUE. - */ - public static int abs(int value) { - if (FM_USE_JDK_MATH || SFM_USE_JDK_MATH) { - return Math.abs(value); - } - return NumbersUtils.abs(value); - } - - /** - * @param value A long value. - * @return The absolute value, except if value is Long.MIN_VALUE, for which it returns Long.MIN_VALUE. - */ - public static long abs(long value) { - if (FM_USE_JDK_MATH || SFM_USE_JDK_MATH) { - return Math.abs(value); - } - return NumbersUtils.abs(value); - } - - /* - * close values - */ - - /** - * @param value A long value. - * @return The specified value as int. - * @throws ArithmeticException if the specified value is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. - */ - public static int toIntExact(long value) { - return NumbersUtils.asInt(value); - } - - /** - * @param value A long value. - * @return The closest int value in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. - */ - public static int toInt(long value) { - return NumbersUtils.toInt(value); - } - - /* - * ranges - */ - - /** - * @param min An int value. - * @param max An int value. - * @param value An int value. - * @return minValue if value < minValue, maxValue if value > maxValue, value otherwise. - */ - public static int toRange(int min, int max, int value) { - return NumbersUtils.toRange(min, max, value); - } - - /** - * @param min A long value. - * @param max A long value. - * @param value A long value. - * @return min if value < min, max if value > max, value otherwise. - */ - public static long toRange(long min, long max, long value) { - return NumbersUtils.toRange(min, max, value); - } - - /* - * unary operators (increment,decrement,negate) - */ - - /** - * @param value An int value. - * @return The argument incremented by one. - * @throws ArithmeticException if the mathematical result - * is not in int range. - */ - public static int incrementExact(int value) { - if (value == Integer.MAX_VALUE) { - throw new ArithmeticException("integer overflow"); - } - return value + 1; - } - - /** - * @param value A long value. - * @return The argument incremented by one. - * @throws ArithmeticException if the mathematical result - * is not in long range. - */ - public static long incrementExact(long value) { - if (value == Long.MAX_VALUE) { - throw new ArithmeticException("long overflow"); - } - return value + 1L; - } - - /** - * @param value An int value. - * @return The argument incremented by one, or the argument - * if the mathematical result is not in int range. - */ - public static int incrementBounded(int value) { - if (value == Integer.MAX_VALUE) { - return value; - } - return value + 1; - } - - /** - * @param value A long value. - * @return The argument incremented by one, or the argument - * if the mathematical result is not in long range. - */ - public static long incrementBounded(long value) { - if (value == Long.MAX_VALUE) { - return value; - } - return value + 1L; - } - - /** - * @param value An int value. - * @return The argument decremented by one. - * @throws ArithmeticException if the mathematical result - * is not in int range. - */ - public static int decrementExact(int value) { - if (value == Integer.MIN_VALUE) { - throw new ArithmeticException("integer overflow"); - } - return value - 1; - } - - /** - * @param value A long value. - * @return The argument decremented by one. - * @throws ArithmeticException if the mathematical result - * is not in long range. - */ - public static long decrementExact(long value) { - if (value == Long.MIN_VALUE) { - throw new ArithmeticException("long overflow"); - } - return value - 1L; - } - - /** - * @param value An int value. - * @return The argument decremented by one, or the argument - * if the mathematical result is not in int range. - */ - public static int decrementBounded(int value) { - if (value == Integer.MIN_VALUE) { - return value; - } - return value - 1; - } - - /** - * @param value A long value. - * @return The argument decremented by one, or the argument - * if the mathematical result is not in long range. - */ - public static long decrementBounded(long value) { - if (value == Long.MIN_VALUE) { - return value; - } - return value - 1L; - } - - /** - * @param value An int value. - * @return The argument negated. - * @throws ArithmeticException if the mathematical result - * is not in int range. - */ - public static int negateExact(int value) { - if (value == Integer.MIN_VALUE) { - throw new ArithmeticException("integer overflow"); - } - return -value; - } - - /** - * @param value A long value. - * @return The argument negated. - * @throws ArithmeticException if the mathematical result - * is not in long range. - */ - public static long negateExact(long value) { - if (value == Long.MIN_VALUE) { - throw new ArithmeticException("long overflow"); - } - return -value; - } - - /** - * @param value An int value. - * @return The argument negated, or Integer.MAX_VALUE - * if the argument is Integer.MIN_VALUE. - */ - public static int negateBounded(int value) { - if (value == Integer.MIN_VALUE) { - return Integer.MAX_VALUE; - } - return -value; - } - - /** - * @param value A long value. - * @return The argument negated, or Long.MAX_VALUE - * if the argument is Long.MIN_VALUE. - */ - public static long negateBounded(long value) { - if (value == Long.MIN_VALUE) { - return Long.MAX_VALUE; - } - return -value; - } - - /* - * binary operators (+,-,*) - */ - - /** - * @param a An int value. - * @param b An int value. - * @return The mathematical result of a+b. - * @throws ArithmeticException if the mathematical result of a+b is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. - */ - public static int addExact(int a, int b) { - return NumbersUtils.plusExact(a, b); - } - - /** - * @param a A long value. - * @param b A long value. - * @return The mathematical result of a+b. - * @throws ArithmeticException if the mathematical result of a+b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. - */ - public static long addExact(long a, long b) { - return NumbersUtils.plusExact(a, b); - } - - /** - * @param a An int value. - * @param b An int value. - * @return The int value of [Integer.MIN_VALUE,Integer.MAX_VALUE] range which is the closest to mathematical result of a+b. - */ - public static int addBounded(int a, int b) { - return NumbersUtils.plusBounded(a, b); - } - - /** - * @param a A long value. - * @param b A long value. - * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a+b. - */ - public static long addBounded(long a, long b) { - return NumbersUtils.plusBounded(a, b); - } - - /** - * @param a An int value. - * @param b An int value. - * @return The mathematical result of a-b. - * @throws ArithmeticException if the mathematical result of a-b is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. - */ - public static int subtractExact(int a, int b) { - return NumbersUtils.minusExact(a, b); - } - - /** - * @param a A long value. - * @param b A long value. - * @return The mathematical result of a-b. - * @throws ArithmeticException if the mathematical result of a-b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. - */ - public static long subtractExact(long a, long b) { - return NumbersUtils.minusExact(a, b); - } - - /** - * @param a An int value. - * @param b An int value. - * @return The int value of [Integer.MIN_VALUE,Integer.MAX_VALUE] range which is the closest to mathematical result of a-b. - */ - public static int subtractBounded(int a, int b) { - return NumbersUtils.minusBounded(a, b); - } - - /** - * @param a A long value. - * @param b A long value. - * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a-b. - */ - public static long subtractBounded(long a, long b) { - return NumbersUtils.minusBounded(a, b); - } - - /** - * @param a An int value. - * @param b An int value. - * @return The mathematical result of a*b. - * @throws ArithmeticException if the mathematical result of a*b is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. - */ - public static int multiplyExact(int a, int b) { - return NumbersUtils.timesExact(a, b); - } - - /** - * @param a A long value. - * @param b An int value. - * @return The mathematical result of a*b. - * @throws ArithmeticException if the mathematical result of a*b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. - */ - public static long multiplyExact(long a, int b) { - return NumbersUtils.timesExact(a, (long) b); - } - - /** - * @param a A long value. - * @param b A long value. - * @return The mathematical result of a*b. - * @throws ArithmeticException if the mathematical result of a*b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. - */ - public static long multiplyExact(long a, long b) { - return NumbersUtils.timesExact(a, b); - } - - /** - * @param a An int value. - * @param b An int value. - * @return The int value of [Integer.MIN_VALUE,Integer.MAX_VALUE] range which is the closest to mathematical result of a*b. - */ - public static int multiplyBounded(int a, int b) { - return NumbersUtils.timesBounded(a, b); - } - - /** - * @param a A long value. - * @param b An int value. - * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a*b. - */ - public static long multiplyBounded(long a, int b) { - return NumbersUtils.timesBounded(a, (long) b); - } - - /** - * @param a A long value. - * @param b A long value. - * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a*b. - */ - public static long multiplyBounded(long a, long b) { - return NumbersUtils.timesBounded(a, b); - } - - /** - * @param x An int value. - * @param y An int value. - * @return The mathematical product as a long. - */ - public static long multiplyFull(int x, int y) { - return ((long) x) * ((long) y); - } - - /** - * @param x A long value. - * @param y A long value. - * @return The most significant 64 bits of the 128-bit product of two 64-bit factors. - */ - public static long multiplyHigh(long x, long y) { - if ((x|y) < 0) { - // Use technique from section 8-2 of Henry S. Warren, Jr., - // Hacker's Delight (2nd ed.) (Addison Wesley, 2013), 173-174. - long x1 = (x >> 32); - long y1 = (y >> 32); - long x2 = (x & 0xFFFFFFFFL); - long y2 = (y & 0xFFFFFFFFL); - long z2 = x2 * y2; - long t = x1 * y2 + (z2 >>> 32); - long z1 = (t & 0xFFFFFFFFL) + x2 * y1; - long z0 = (t >> 32); - return x1 * y1 + z0 + (z1 >> 32); - } else { - // Use Karatsuba technique with two base 2^32 digits. - long x1 = (x >>> 32); - long y1 = (y >>> 32); - long x2 = (x & 0xFFFFFFFFL); - long y2 = (y & 0xFFFFFFFFL); - long A = x1 * y1; - long B = x2 * y2; - long C = (x1 + x2) * (y1 + y2); - long K = C - A - B; - return (((B >>> 32) + K) >>> 32) + A; - } - } - - /* - * binary operators (/,%) - */ - - /** - * Returns the largest int <= dividend/divisor. - * - * Unlike "/" operator, which rounds towards 0, this division - * rounds towards -Infinity (which give different result - * when the exact result is negative). - * - * @param x The dividend. - * @param y The divisor. - * @return The largest int <= dividend/divisor, unless dividend is - * Integer.MIN_VALUE and divisor is -1, in which case - * Integer.MIN_VALUE is returned. - * @throws ArithmeticException if the divisor is zero. - */ - public static int floorDiv(int x, int y) { - int r = x / y; - // If the signs are different and modulo not zero, rounding down. - if (((x ^ y) < 0) && ((r * y) != x)) { - r--; - } - return r; - } - - /** - * Returns the largest long <= dividend/divisor. - * - * Unlike "/" operator, which rounds towards 0, this division - * rounds towards -Infinity (which give different result - * when the exact result is negative). - * - * @param x The dividend. - * @param y The divisor. - * @return The largest long <= dividend/divisor, unless dividend is - * Long.MIN_VALUE and divisor is -1, in which case - * Long.MIN_VALUE is returned. - * @throws ArithmeticException if the divisor is zero. - */ - public static long floorDiv(long x, int y) { - return floorDiv(x, (long) y); - } - - /** - * Returns the largest long <= dividend/divisor. - * - * Unlike "/" operator, which rounds towards 0, this division - * rounds towards -Infinity (which give different result - * when the exact result is negative). - * - * @param x The dividend. - * @param y The divisor. - * @return The largest long <= dividend/divisor, unless dividend is - * Long.MIN_VALUE and divisor is -1, in which case - * Long.MIN_VALUE is returned. - * @throws ArithmeticException if the divisor is zero. - */ - public static long floorDiv(long x, long y) { - long r = x / y; - // If the signs are different and modulo not zero, rounding down. - if (((x ^ y) < 0) && ((r * y) != x)) { - r--; - } - return r; - } - - /** - * Returns the floor modulus, which is "x - floorDiv(x,y) * y", - * has the same sign as y, and is in ]-abs(y),abs(y)[. - * - * The relationship between floorMod and floorDiv is the same - * than between "%" and "/". - * - * @param x The dividend. - * @param y The divisor. - * @return The floor modulus, i.e. "x - (floorDiv(x, y) * y)". - * @throws ArithmeticException if the divisor is zero. - */ - public static int floorMod(int x, int y) { - return x - floorDiv(x, y) * y; - } - - /** - * Returns the floor modulus, which is "x - floorDiv(x,y) * y", - * has the same sign as y, and is in ]-abs(y),abs(y)[. - * - * The relationship between floorMod and floorDiv is the same - * than between "%" and "/". - * - * @param x The dividend. - * @param y The divisor. - * @return The floor modulus, i.e. "x - (floorDiv(x, y) * y)". - * @throws ArithmeticException if the divisor is zero. - */ - public static int floorMod(long x, int y) { - // No overflow so can cast. - return (int) (x - floorDiv(x,y) * y); - } - - /** - * Returns the floor modulus, which is "x - floorDiv(x,y) * y", - * has the same sign as y, and is in ]-abs(y),abs(y)[. - * - * The relationship between floorMod and floorDiv is the same - * than between "%" and "/". - * - * @param x The dividend. - * @param y The divisor. - * @return The floor modulus, i.e. "x - (floorDiv(x, y) * y)". - * @throws ArithmeticException if the divisor is zero. - */ - public static long floorMod(long x, long y) { - return x - floorDiv(x, y) * y; - } - - /* - * Non-redefined Math public values and treatments. - */ - - public static int min(int a, int b) { - return Math.min(a,b); - } - - public static long min(long a, long b) { - return Math.min(a,b); - } - - public static int max(int a, int b) { - return Math.max(a,b); - } - - public static long max(long a, long b) { - return Math.max(a,b); - } - - //-------------------------------------------------------------------------- - // PACKAGE-PRIVATE METHODS - //-------------------------------------------------------------------------- - - /** - * @param power Must be in normal values range. - */ - static double twoPowNormal(int power) { - if (USE_TWO_POW_TAB) { - return MyTTwoPow.twoPowTab[power-MIN_DOUBLE_EXPONENT]; - } else { - return Double.longBitsToDouble(((long)(power+MAX_DOUBLE_EXPONENT))<<52); - } - } - - /** - * @param power Must be in normal or subnormal values range. - */ - static double twoPowNormalOrSubnormal(int power) { - if (USE_TWO_POW_TAB) { - return MyTTwoPow.twoPowTab[power-MIN_DOUBLE_EXPONENT]; - } else { - if (power <= -MAX_DOUBLE_EXPONENT) { // Not normal. - return Double.longBitsToDouble(0x0008000000000000L>>(-(power+MAX_DOUBLE_EXPONENT))); - } else { // Normal. - return Double.longBitsToDouble(((long)(power+MAX_DOUBLE_EXPONENT))<<52); - } - } - } - - static double atan2_pinf_yyy(double y) { - if (y == Double.POSITIVE_INFINITY) { - return Math.PI/4; - } else if (y == Double.NEGATIVE_INFINITY) { - return -Math.PI/4; - } else if (y > 0.0) { - return 0.0; - } else if (y < 0.0) { - return -0.0; - } else { - return Double.NaN; - } - } - - static double atan2_ninf_yyy(double y) { - if (y == Double.POSITIVE_INFINITY) { - return 3*Math.PI/4; - } else if (y == Double.NEGATIVE_INFINITY) { - return -3*Math.PI/4; - } else if (y > 0.0) { - return Math.PI; - } else if (y < 0.0) { - return -Math.PI; - } else { - return Double.NaN; - } - } - - static double atan2_yyy_zeroOrNaN(double y, double x) { - if (x == 0.0) { - if (y == 0.0) { - if (signFromBit_antiCyclic(x) < 0) { - // x is -0.0 - return signFromBit_antiCyclic(y) * Math.PI; - } else { - // +-0.0 - return y; - } - } - if (y > 0.0) { - return Math.PI/2; - } else if (y < 0.0) { - return -Math.PI/2; - } else { - return Double.NaN; - } - } else { - return Double.NaN; - } - } - - /** - * At least one of the arguments must be NaN. - */ - static double hypot_NaN(double xAbs, double yAbs) { - if ((xAbs == Double.POSITIVE_INFINITY) || (yAbs == Double.POSITIVE_INFINITY)) { - return Double.POSITIVE_INFINITY; - } else { - return Double.NaN; - } - } - - /** - * At least one of the arguments must be NaN. - */ - static double hypot_NaN(double xAbs, double yAbs, double zAbs) { - if ((xAbs == Double.POSITIVE_INFINITY) || (yAbs == Double.POSITIVE_INFINITY) || (zAbs == Double.POSITIVE_INFINITY)) { - return Double.POSITIVE_INFINITY; - } else { - return Double.NaN; - } - } - - /* - * - */ - - /** - * @param remainder Must have 1 for 2nd and 3rd exponent bits, which is the - * case for heavyRemPiO2 remainders (their absolute values are >= - * Double.longBitsToDouble(0x3000000000000000L) - * = 1.727233711018889E-77, and even if they were not, turning these - * bits from 0 to 1 on decoding would not change the absolute error - * much), and also works for +-Infinity or NaN encoding. - * @param quadrant Must be in [0,3]. - * @return Bits holding remainder, and quadrant instead of - * reamainder's 2nd and 3rd exponent bits. - */ - static long encodeRemainderAndQuadrant(double remainder, int quadrant) { - final long bits = Double.doubleToRawLongBits(remainder); - return (bits&QUADRANT_BITS_0_MASK)|(((long)quadrant)<<60); - } - - static double decodeRemainder(long bits) { - return Double.longBitsToDouble((bits&QUADRANT_BITS_0_MASK)|QUADRANT_PLACE_BITS); - } - - static int decodeQuadrant(long bits) { - return ((int)(bits>>60))&3; - } - - /* - * JDK-based remainders. - * Since a strict one for (% (PI/2)) is needed for heavyRemainderPiO2, - * we need it in this class. - * Then, for homogeneity, we put them all in this class. - * Then, to avoid code duplication for these slow-anyway methods, - * we just stick with strict versions, for both FastMath and StrictFastMath. - */ - - /** - * @param angle Angle, in radians. - * @return Remainder of (angle % (2*PI)), in [-PI,PI]. - */ - static strictfp double jdkRemainderTwoPi(double angle) { - final double sin = StrictMath.sin(angle); - final double cos = StrictMath.cos(angle); - return StrictMath.atan2(sin, cos); - } - - /** - * @param angle Angle, in radians. - * @return Remainder of (angle % PI), in [-PI/2,PI/2]. - */ - static strictfp double jdkRemainderPi(double angle) { - final double sin = StrictMath.sin(angle); - final double cos = StrictMath.cos(angle); - /* - * Making sure atan2's result ends up in [-PI/2,PI/2], - * i.e. has maximum accuracy. - */ - return StrictMath.atan2(sin, Math.abs(cos)); - } - - /** - * @param angle Angle, in radians. - * @return Bits of double corresponding to remainder of (angle % (PI/2)), - * in [-PI/4,PI/4], with quadrant encoded in exponent bits. - */ - static strictfp long jdkRemainderPiO2(double angle, boolean negateRem) { - final double sin = StrictMath.sin(angle); - final double cos = StrictMath.cos(angle); - - /* - * Computing quadrant first, and then computing - * atan2, to make sure its result ends up in [-PI/4,PI/4], - * i.e. has maximum accuracy. - */ - - final int q; - final double sinForAtan2; - final double cosForAtan2; - if (cos >= (SQRT_2/2)) { - // [-PI/4,PI/4] - q = 0; - sinForAtan2 = sin; - cosForAtan2 = cos; - } else if (cos <= -(SQRT_2/2)) { - // [3*PI/4,5*PI/4] - q = 2; - sinForAtan2 = -sin; - cosForAtan2 = -cos; - } else if (sin > 0.0) { - // [PI/4,3*PI/4] - q = 1; - sinForAtan2 = -cos; - cosForAtan2 = sin; - } else { - // [5*PI/4,7*PI/4] - q = 3; - sinForAtan2 = cos; - cosForAtan2 = -sin; - } - - double fw = StrictMath.atan2(sinForAtan2, cosForAtan2); - - return encodeRemainderAndQuadrant(negateRem ? -fw : fw, q); - } - - /* - * Our remainders implementations. - */ - - /** - * @param angle Angle, in radians. Must not be NaN nor +-Infinity. - * @return Remainder of (angle % (2*PI)), in [-PI,PI]. - */ - static strictfp double heavyRemainderTwoPi(double angle) { - final long remAndQuad = heavyRemainderPiO2(angle, false); - final double rem = decodeRemainder(remAndQuad); - final int q = decodeQuadrant(remAndQuad); - if (q == 0) { - return rem; - } else if (q == 1) { - return (rem + PIO2_LO) + PIO2_HI; - } else if (q == 2) { - if (rem < 0.0) { - return (rem + PI_LO) + PI_HI; - } else { - return (rem - PI_LO) - PI_HI; - } - } else { - return (rem - PIO2_LO) - PIO2_HI; - } - } - - /** - * @param angle Angle, in radians. Must not be NaN nor +-Infinity. - * @return Remainder of (angle % PI), in [-PI/2,PI/2]. - */ - static strictfp double heavyRemainderPi(double angle) { - final long remAndQuad = heavyRemainderPiO2(angle, false); - final double rem = decodeRemainder(remAndQuad); - final int q = decodeQuadrant(remAndQuad); - if ((q&1) != 0) { - // q is 1 or 3 - if (rem < 0.0) { - return (rem + PIO2_LO) + PIO2_HI; - } else { - return (rem - PIO2_LO) - PIO2_HI; - } - } - return rem; - } - - /** - * Remainder using an accurate definition of PI. - * Derived from a fdlibm treatment called __kernel_rem_pio2. - * - * Not defining a non-strictfp version for FastMath, to avoid duplicating - * its long and messy code, and because it's slow anyway, and should be - * rarely used when speed matters. - * - * @param angle Angle, in radians. Must not be NaN nor +-Infinity. - * @param negateRem True if remainder must be negated before encoded into returned long. - * @return Bits of double corresponding to remainder of (angle % (PI/2)), - * in [-PI/4,PI/4], with quadrant encoded in exponent bits. - */ - static strictfp long heavyRemainderPiO2(double angle, boolean negateRem) { - - /* - * fdlibm treatments unrolled, to avoid garbage and be OOME-free, - * corresponding to: - * 1) initial jk = 4 (precision = 3 = 64 bits (extended)), - * which is more accurate than using precision = 2 - * (53 bits, double), even though we work with doubles - * and use strictfp! - * 2) max lengths of 8 for f[], 6 for q[], fq[] and iq[]. - * 3) at most one recomputation (one goto). - * These limitations were experimentally found to - * be sufficient for billions of random doubles - * of random magnitudes. - * For the rare cases that our unrolled treatments can't handle, - * we fall back to a JDK-based implementation. - */ - - int n,i,j,ih; - double fw; - - /* - * Turning angle into 24-bits integer chunks. - * Done outside __kernel_rem_pio2, but we factor it inside our method. - */ - - // Reworking exponent to have a value < 2^24. - final long lx = Double.doubleToRawLongBits(angle); - final long exp = ((lx>>52)&0x7FF) - (1023+23); - double z = Double.longBitsToDouble(lx - (exp<<52)); - - double x0 = (double)(int)z; - z = (z-x0)*TWO_POW_24; - double x1 = (double)(int)z; - z = (z-x1)*TWO_POW_24; - double x2 = (double)(int)z; - - final int e0 = (int)exp; - // in [1,3] - final int nx = (x2 == 0.0) ? ((x1 == 0.0) ? 1 : 2) : 3; - - /* - * - */ - - double f0,f1,f2,f3,f4,f5,f6,f7; - double q0,q1,q2,q3,q4,q5; - int iq0,iq1,iq2,iq3,iq4,iq5; - - int jk = 4; - - int jx = nx-1; - int jv = Math.max(0,(e0-3)/24); - // In fdlibm, this is q0, but we prefer to use q0 for q[0]. - int qZero = e0-24*(jv+1); - - j = jv-jx; - if (jx == 0) { - f6 = 0.0; - f5 = 0.0; - f4 = (j >= -4) ? TWO_OVER_PI_TAB[j+4] : 0.0; - f3 = (j >= -3) ? TWO_OVER_PI_TAB[j+3] : 0.0; - f2 = (j >= -2) ? TWO_OVER_PI_TAB[j+2] : 0.0; - f1 = (j >= -1) ? TWO_OVER_PI_TAB[j+1] : 0.0; - f0 = (j >= 0) ? TWO_OVER_PI_TAB[j] : 0.0; - - q0 = x0*f0; - q1 = x0*f1; - q2 = x0*f2; - q3 = x0*f3; - q4 = x0*f4; - } else if (jx == 1) { - f6 = 0.0; - f5 = (j >= -5) ? TWO_OVER_PI_TAB[j+5] : 0.0; - f4 = (j >= -4) ? TWO_OVER_PI_TAB[j+4] : 0.0; - f3 = (j >= -3) ? TWO_OVER_PI_TAB[j+3] : 0.0; - f2 = (j >= -2) ? TWO_OVER_PI_TAB[j+2] : 0.0; - f1 = (j >= -1) ? TWO_OVER_PI_TAB[j+1] : 0.0; - f0 = (j >= 0) ? TWO_OVER_PI_TAB[j] : 0.0; - - q0 = x0*f1 + x1*f0; - q1 = x0*f2 + x1*f1; - q2 = x0*f3 + x1*f2; - q3 = x0*f4 + x1*f3; - q4 = x0*f5 + x1*f4; - } else { // jx == 2 - f6 = (j >= -6) ? TWO_OVER_PI_TAB[j+6] : 0.0; - f5 = (j >= -5) ? TWO_OVER_PI_TAB[j+5] : 0.0; - f4 = (j >= -4) ? TWO_OVER_PI_TAB[j+4] : 0.0; - f3 = (j >= -3) ? TWO_OVER_PI_TAB[j+3] : 0.0; - f2 = (j >= -2) ? TWO_OVER_PI_TAB[j+2] : 0.0; - f1 = (j >= -1) ? TWO_OVER_PI_TAB[j+1] : 0.0; - f0 = (j >= 0) ? TWO_OVER_PI_TAB[j] : 0.0; - - q0 = x0*f2 + x1*f1 + x2*f0; - q1 = x0*f3 + x1*f2 + x2*f1; - q2 = x0*f4 + x1*f3 + x2*f2; - q3 = x0*f5 + x1*f4 + x2*f3; - q4 = x0*f6 + x1*f5 + x2*f4; - } - - double twoPowQZero = twoPowNormal(qZero); - - int jz = jk; - - /* - * Unrolling of first round. - */ - - z = q4; - fw = (double)(int)(TWO_POW_N24*z); - iq0 = (int)(z-TWO_POW_24*fw); - z = q3+fw; - fw = (double)(int)(TWO_POW_N24*z); - iq1 = (int)(z-TWO_POW_24*fw); - z = q2+fw; - fw = (double)(int)(TWO_POW_N24*z); - iq2 = (int)(z-TWO_POW_24*fw); - z = q1+fw; - fw = (double)(int)(TWO_POW_N24*z); - iq3 = (int)(z-TWO_POW_24*fw); - z = q0+fw; - iq4 = 0; - iq5 = 0; - - z = (z*twoPowQZero) % 8.0; - n = (int)z; - z -= (double)n; - - ih = 0; - if (qZero > 0) { - // Parentheses against code formatter bug. - i = (iq3>>(24-qZero)); - n += i; - iq3 -= i<<(24-qZero); - ih = iq3>>(23-qZero); - } else if (qZero == 0) { - ih = iq3>>23; - } else if (z >= 0.5) { - ih = 2; - } - - if (ih > 0) { - n += 1; - // carry = 1 is common case, - // so using it as initial value. - int carry = 1; - if (iq0 != 0) { - iq0 = 0x1000000 - iq0; - iq1 = 0xFFFFFF - iq1; - iq2 = 0xFFFFFF - iq2; - iq3 = 0xFFFFFF - iq3; - } else if (iq1 != 0) { - iq1 = 0x1000000 - iq1; - iq2 = 0xFFFFFF - iq2; - iq3 = 0xFFFFFF - iq3; - } else if (iq2 != 0) { - iq2 = 0x1000000 - iq2; - iq3 = 0xFFFFFF - iq3; - } else if (iq3 != 0) { - iq3 = 0x1000000 - iq3; - } else { - carry = 0; - } - if (qZero > 0) { - if (qZero == 1) { - iq3 &= 0x7FFFFF; - } else if (qZero == 2) { - iq3 &= 0x3FFFFF; - } - } - if (ih == 2) { - z = 1.0 - z; - if (carry != 0) { - z -= twoPowQZero; - } - } - } - - if (z == 0.0) { - if (iq3 == 0) { - // With random values of random magnitude, - // probability for this to happen seems lower than 1e-6. - // jz would be more than just incremented by one, - // which our unrolling doesn't support. - return jdkRemainderPiO2(angle, negateRem); - } - if (jx == 0) { - f5 = TWO_OVER_PI_TAB[jv+5]; - q5 = x0*f5; - } else if (jx == 1) { - f6 = TWO_OVER_PI_TAB[jv+5]; - q5 = x0*f6 + x1*f5; - } else { // jx == 2 - f7 = TWO_OVER_PI_TAB[jv+5]; - q5 = x0*f7 + x1*f6 + x2*f5; - } - - jz++; - - /* - * Unrolling of second round. - */ - - z = q5; - fw = (double)(int)(TWO_POW_N24*z); - iq0 = (int)(z-TWO_POW_24*fw); - z = q4+fw; - fw = (double)(int)(TWO_POW_N24*z); - iq1 = (int)(z-TWO_POW_24*fw); - z = q3+fw; - fw = (double)(int)(TWO_POW_N24*z); - iq2 = (int)(z-TWO_POW_24*fw); - z = q2+fw; - fw = (double)(int)(TWO_POW_N24*z); - iq3 = (int)(z-TWO_POW_24*fw); - z = q1+fw; - fw = (double)(int)(TWO_POW_N24*z); - iq4 = (int)(z-TWO_POW_24*fw); - z = q0+fw; - iq5 = 0; - - z = (z*twoPowQZero) % 8.0; - n = (int)z; - z -= (double)n; - - ih = 0; - if (qZero > 0) { - // Parentheses against code formatter bug. - i = (iq4>>(24-qZero)); - n += i; - iq4 -= i<<(24-qZero); - ih = iq4>>(23-qZero); - } else if (qZero == 0) { - ih = iq4>>23; - } else if (z >= 0.5) { - ih = 2; - } - - if (ih > 0) { - n += 1; - // carry = 1 is common case, - // so using it as initial value. - int carry = 1; - if (iq0 != 0) { - iq0 = 0x1000000 - iq0; - iq1 = 0xFFFFFF - iq1; - iq2 = 0xFFFFFF - iq2; - iq3 = 0xFFFFFF - iq3; - iq4 = 0xFFFFFF - iq4; - } else if (iq1 != 0) { - iq1 = 0x1000000 - iq1; - iq2 = 0xFFFFFF - iq2; - iq3 = 0xFFFFFF - iq3; - iq4 = 0xFFFFFF - iq4; - } else if (iq2 != 0) { - iq2 = 0x1000000 - iq2; - iq3 = 0xFFFFFF - iq3; - iq4 = 0xFFFFFF - iq4; - } else if (iq3 != 0) { - iq3 = 0x1000000 - iq3; - iq4 = 0xFFFFFF - iq4; - } else if (iq4 != 0) { - iq4 = 0x1000000 - iq4; - } else { - carry = 0; - } - if (qZero > 0) { - if (qZero == 1) { - iq4 &= 0x7FFFFF; - } else if (qZero == 2) { - iq4 &= 0x3FFFFF; - } - } - if (ih == 2) { - z = 1.0 - z; - if (carry != 0) { - z -= twoPowQZero; - } - } - } - - if (z == 0.0) { - if (iq4 == 0) { - // Case not encountered in tests, but still handling it. - // Would require a third loop unrolling. - return jdkRemainderPiO2(angle, negateRem); - } else { - // z == 0.0, and iq4 != 0, - // so we remove 24 from qZero only once, - // but since we no longer use qZero, - // we just bother to multiply its 2-power - // by 2^-24. - jz--; - twoPowQZero *= TWO_POW_N24; - } - } else { - // z != 0.0 at end of second round. - } - } else { - // z != 0.0 at end of first round. - } - - /* - * After loop. - */ - - if (z != 0.0) { - z /= twoPowQZero; - if (z >= TWO_POW_24) { - fw = (double)(int)(TWO_POW_N24*z); - if (jz == jk) { - iq4 = (int)(z-TWO_POW_24*fw); - jz++; // jz to 5 - // Not using qZero anymore so not updating it. - twoPowQZero *= TWO_POW_24; - iq5 = (int)fw; - } else { // jz == jk+1 == 5 - // Case not encountered in tests, but still handling it. - // Would require use of iq6, with jz = 6. - return jdkRemainderPiO2(angle, negateRem); - } - } else { - if (jz == jk) { - iq4 = (int)z; - } else { // jz == jk+1 == 5 - // Case not encountered in tests, but still handling it. - iq5 = (int)z; - } - } - } - - fw = twoPowQZero; - - if (jz == 5) { - q5 = fw*(double)iq5; - fw *= TWO_POW_N24; - } else { - q5 = 0.0; - } - q4 = fw*(double)iq4; - fw *= TWO_POW_N24; - q3 = fw*(double)iq3; - fw *= TWO_POW_N24; - q2 = fw*(double)iq2; - fw *= TWO_POW_N24; - q1 = fw*(double)iq1; - fw *= TWO_POW_N24; - q0 = fw*(double)iq0; - - /* - * We just use HI part of the result. - */ - - fw = PIO2_TAB0*q5; - fw += PIO2_TAB0*q4 + PIO2_TAB1*q5; - fw += PIO2_TAB0*q3 + PIO2_TAB1*q4 + PIO2_TAB2*q5; - fw += PIO2_TAB0*q2 + PIO2_TAB1*q3 + PIO2_TAB2*q4 + PIO2_TAB3*q5; - fw += PIO2_TAB0*q1 + PIO2_TAB1*q2 + PIO2_TAB2*q3 + PIO2_TAB3*q4 + PIO2_TAB4*q5; - fw += PIO2_TAB0*q0 + PIO2_TAB1*q1 + PIO2_TAB2*q2 + PIO2_TAB3*q3 + PIO2_TAB4*q4 + PIO2_TAB5*q5; - - if ((ih != 0) ^ negateRem) { - fw = -fw; - } - - return encodeRemainderAndQuadrant(fw, n&3); - } - - //-------------------------------------------------------------------------- - // PRIVATE METHODS - //-------------------------------------------------------------------------- - - /** - * Redefined here, to avoid cyclic dependency with (Strict)FastMath. - * - * @param value A double value. - * @return -1 if sign bit is 1, 1 if sign bit is 0. - */ - private static long signFromBit_antiCyclic(double value) { - // Returning a long, to avoid useless cast into int. - return ((Double.doubleToRawLongBits(value)>>62)|1); - } - - private static boolean getBooleanProperty( - final String key, - boolean defaultValue) { - final String tmp = System.getProperty(key); - if (tmp != null) { - return Boolean.parseBoolean(tmp); - } else { - return defaultValue; - } - } - - /** - * Use look-up tables size power through this method, - * to make sure is it small in case java.lang.Math - * is directly used. - */ - private static int getTabSizePower(int tabSizePower) { - return (FM_USE_JDK_MATH && SFM_USE_JDK_MATH) ? Math.min(2, tabSizePower) : tabSizePower; - } -} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/DoubleWrapper.java b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/DoubleWrapper.java deleted file mode 100644 index e7adc8d59..000000000 --- a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/DoubleWrapper.java +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ -package space.kscience.kmath.jafama; - -public class DoubleWrapper { - public double value; - @Override - public String toString() { - return Double.toString(this.value); - } -} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/FastMath.java b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/FastMath.java deleted file mode 100644 index a83c01f7b..000000000 --- a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/FastMath.java +++ /dev/null @@ -1,2986 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.jafama; - -/** - * Faster (hopefully) versions of java.lang.Math methods, plus additional ones. - * Cf. README.txt for more info. - */ -public final class FastMath extends CmnFastMath { - - //-------------------------------------------------------------------------- - // CONFIGURATION - //-------------------------------------------------------------------------- - - private static final boolean USE_JDK_MATH = FM_USE_JDK_MATH; - - private static final boolean USE_REDEFINED_LOG = FM_USE_REDEFINED_LOG; - - private static final boolean USE_REDEFINED_SQRT = FM_USE_REDEFINED_SQRT; - - private static final boolean USE_POWTABS_FOR_ASIN = FM_USE_POWTABS_FOR_ASIN; - - //-------------------------------------------------------------------------- - // PUBLIC METHODS - //-------------------------------------------------------------------------- - - /* - * trigonometry - */ - - /** - * @param angle Angle in radians. - * @return Angle sine. - */ - public static double sin(double angle) { - if (USE_JDK_MATH) { - return Math.sin(angle); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - if (angle > SIN_COS_MAX_VALUE_FOR_INT_MODULO) { - if (false) { - // Can give very bad relative error near PI (mod 2*PI). - angle = remainderTwoPi(angle); - if (angle < 0.0) { - angle = -angle; - negateResult = !negateResult; - } - } else { - final long remAndQuad = remainderPiO2(angle); - angle = decodeRemainder(remAndQuad); - final double sin; - final int q = decodeQuadrant(remAndQuad); - if (q == 0) { - sin = sin(angle); - } else if (q == 1) { - sin = cos(angle); - } else if (q == 2) { - sin = -sin(angle); - } else { - sin = -cos(angle); - } - return (negateResult ? -sin : sin); - } - } - // index: possibly outside tables range. - int index = (int)(angle * SIN_COS_INDEXER + 0.5); - double delta = (angle - index * SIN_COS_DELTA_HI) - index * SIN_COS_DELTA_LO; - // Making sure index is within tables range. - // Last value of each table is the same than first, - // so we ignore it (tabs size minus one) for modulo. - index &= (SIN_COS_TABS_SIZE-2); // index % (SIN_COS_TABS_SIZE-1) - double indexSin = MyTSinCos.sinTab[index]; - double indexCos = MyTSinCos.cosTab[index]; - double result = indexSin + delta * (indexCos + delta * (-indexSin * ONE_DIV_F2 + delta * (-indexCos * ONE_DIV_F3 + delta * indexSin * ONE_DIV_F4))); - return negateResult ? -result : result; - } - - /** - * Quick sin, with accuracy of about 1.6e-3 (PI/) - * for |angle| < 6588395.0 (Integer.MAX_VALUE * (2*PI/) - 2) - * (- 2 due to removing PI/2 before using cosine tab), - * and no accuracy at all for larger values. - * - * @param angle Angle in radians. - * @return Angle sine. - */ - public static double sinQuick(double angle) { - if (USE_JDK_MATH) { - return Math.sin(angle); - } - return MyTSinCos.cosTab[((int)(Math.abs(angle-Math.PI/2) * SIN_COS_INDEXER + 0.5)) & (SIN_COS_TABS_SIZE-2)]; - } - - /** - * @param angle Angle in radians. - * @return Angle cosine. - */ - public static double cos(double angle) { - if (USE_JDK_MATH) { - return Math.cos(angle); - } - angle = Math.abs(angle); - if (angle > SIN_COS_MAX_VALUE_FOR_INT_MODULO) { - if (false) { - // Can give very bad relative error near PI (mod 2*PI). - angle = remainderTwoPi(angle); - if (angle < 0.0) { - angle = -angle; - } - } else { - final long remAndQuad = remainderPiO2(angle); - angle = decodeRemainder(remAndQuad); - final double cos; - final int q = decodeQuadrant(remAndQuad); - if (q == 0) { - cos = cos(angle); - } else if (q == 1) { - cos = -sin(angle); - } else if (q == 2) { - cos = -cos(angle); - } else { - cos = sin(angle); - } - return cos; - } - } - // index: possibly outside tables range. - int index = (int)(angle * SIN_COS_INDEXER + 0.5); - double delta = (angle - index * SIN_COS_DELTA_HI) - index * SIN_COS_DELTA_LO; - // Making sure index is within tables range. - // Last value of each table is the same than first, - // so we ignore it (tabs size minus one) for modulo. - index &= (SIN_COS_TABS_SIZE-2); // index % (SIN_COS_TABS_SIZE-1) - double indexCos = MyTSinCos.cosTab[index]; - double indexSin = MyTSinCos.sinTab[index]; - return indexCos + delta * (-indexSin + delta * (-indexCos * ONE_DIV_F2 + delta * (indexSin * ONE_DIV_F3 + delta * indexCos * ONE_DIV_F4))); - } - - /** - * Quick cos, with accuracy of about 1.6e-3 (PI/) - * for |angle| < 6588397.0 (Integer.MAX_VALUE * (2*PI/)), - * and no accuracy at all for larger values. - * - * @param angle Angle in radians. - * @return Angle cosine. - */ - public static double cosQuick(double angle) { - if (USE_JDK_MATH) { - return Math.cos(angle); - } - return MyTSinCos.cosTab[((int)(Math.abs(angle) * SIN_COS_INDEXER + 0.5)) & (SIN_COS_TABS_SIZE-2)]; - } - - /** - * Computes sine and cosine together. - * - * @param angle Angle in radians. - * @param cosine (out) Angle cosine. - * @return Angle sine. - */ - public static double sinAndCos(double angle, DoubleWrapper cosine) { - if (USE_JDK_MATH) { - cosine.value = Math.cos(angle); - return Math.sin(angle); - } - // Using the same algorithm than sin(double) method, - // and computing also cosine at the end. - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - if (angle > SIN_COS_MAX_VALUE_FOR_INT_MODULO) { - if (false) { - // Can give very bad relative error near PI (mod 2*PI). - angle = remainderTwoPi(angle); - if (angle < 0.0) { - angle = -angle; - negateResult = !negateResult; - } - } else { - final long remAndQuad = remainderPiO2(angle); - angle = decodeRemainder(remAndQuad); - final double sin; - final int q = decodeQuadrant(remAndQuad); - if (q == 0) { - sin = sin(angle); - cosine.value = cos(angle); - } else if (q == 1) { - sin = cos(angle); - cosine.value = -sin(angle); - } else if (q == 2) { - sin = -sin(angle); - cosine.value = -cos(angle); - } else { - sin = -cos(angle); - cosine.value = sin(angle); - } - return (negateResult ? -sin : sin); - } - } - int index = (int)(angle * SIN_COS_INDEXER + 0.5); - double delta = (angle - index * SIN_COS_DELTA_HI) - index * SIN_COS_DELTA_LO; - index &= (SIN_COS_TABS_SIZE-2); // index % (SIN_COS_TABS_SIZE-1) - double indexSin = MyTSinCos.sinTab[index]; - double indexCos = MyTSinCos.cosTab[index]; - // Could factor some multiplications (delta * factorials), but then is less accurate. - cosine.value = indexCos + delta * (-indexSin + delta * (-indexCos * ONE_DIV_F2 + delta * (indexSin * ONE_DIV_F3 + delta * indexCos * ONE_DIV_F4))); - double result = indexSin + delta * (indexCos + delta * (-indexSin * ONE_DIV_F2 + delta * (-indexCos * ONE_DIV_F3 + delta * indexSin * ONE_DIV_F4))); - return negateResult ? -result : result; - } - - /** - * Can have very bad relative error near +-PI/2, - * but of the same magnitude than the relative delta between - * StrictMath.tan(PI/2) and StrictMath.tan(nextDown(PI/2)). - * - * @param angle Angle in radians. - * @return Angle tangent. - */ - public static double tan(double angle) { - if (USE_JDK_MATH) { - return Math.tan(angle); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - if (angle > TAN_MAX_VALUE_FOR_INT_MODULO) { - angle = remainderPi(angle); - if (angle < 0.0) { - angle = -angle; - negateResult = !negateResult; - } - } - // index: possibly outside tables range. - int index = (int)(angle * TAN_INDEXER + 0.5); - double delta = (angle - index * TAN_DELTA_HI) - index * TAN_DELTA_LO; - // Making sure index is within tables range. - // index modulo PI, i.e. 2*(virtual tab size minus one). - index &= (2*(TAN_VIRTUAL_TABS_SIZE-1)-1); // index % (2*(TAN_VIRTUAL_TABS_SIZE-1)) - // Here, index is in [0,2*(TAN_VIRTUAL_TABS_SIZE-1)-1], i.e. indicates an angle in [0,PI[. - if (index > (TAN_VIRTUAL_TABS_SIZE-1)) { - index = (2*(TAN_VIRTUAL_TABS_SIZE-1)) - index; - delta = -delta; - negateResult = !negateResult; - } - double result; - if (index < TAN_TABS_SIZE) { - result = MyTTan.tanTab[index] - + delta * (MyTTan.tanDer1DivF1Tab[index] - + delta * (MyTTan.tanDer2DivF2Tab[index] - + delta * (MyTTan.tanDer3DivF3Tab[index] - + delta * MyTTan.tanDer4DivF4Tab[index]))); - } else { // angle in ]TAN_MAX_VALUE_FOR_TABS,TAN_MAX_VALUE_FOR_INT_MODULO], or angle is NaN - // Using tan(angle) == 1/tan(PI/2-angle) formula: changing angle (index and delta), and inverting. - index = (TAN_VIRTUAL_TABS_SIZE-1) - index; - result = 1/(MyTTan.tanTab[index] - - delta * (MyTTan.tanDer1DivF1Tab[index] - - delta * (MyTTan.tanDer2DivF2Tab[index] - - delta * (MyTTan.tanDer3DivF3Tab[index] - - delta * MyTTan.tanDer4DivF4Tab[index])))); - } - return negateResult ? -result : result; - } - - /** - * @param value Value in [-1,1]. - * @return Value arcsine, in radians, in [-PI/2,PI/2]. - */ - public static double asin(double value) { - if (USE_JDK_MATH) { - return Math.asin(value); - } - boolean negateResult = false; - if (value < 0.0) { - value = -value; - negateResult = true; - } - if (value <= ASIN_MAX_VALUE_FOR_TABS) { - int index = (int)(value * ASIN_INDEXER + 0.5); - double delta = value - index * ASIN_DELTA; - double result = MyTAsin.asinTab[index] - + delta * (MyTAsin.asinDer1DivF1Tab[index] - + delta * (MyTAsin.asinDer2DivF2Tab[index] - + delta * (MyTAsin.asinDer3DivF3Tab[index] - + delta * MyTAsin.asinDer4DivF4Tab[index]))); - return negateResult ? -result : result; - } else if (USE_POWTABS_FOR_ASIN && (value <= ASIN_MAX_VALUE_FOR_POWTABS)) { - int index = (int)(powFast(value * ASIN_POWTABS_ONE_DIV_MAX_VALUE, ASIN_POWTABS_POWER) * ASIN_POWTABS_SIZE_MINUS_ONE + 0.5); - double delta = value - MyTAsinPow.asinParamPowTab[index]; - double result = MyTAsinPow.asinPowTab[index] - + delta * (MyTAsinPow.asinDer1DivF1PowTab[index] - + delta * (MyTAsinPow.asinDer2DivF2PowTab[index] - + delta * (MyTAsinPow.asinDer3DivF3PowTab[index] - + delta * MyTAsinPow.asinDer4DivF4PowTab[index]))); - return negateResult ? -result : result; - } else { // value > ASIN_MAX_VALUE_FOR_TABS, or value is NaN - // This part is derived from fdlibm. - if (value < 1.0) { - double t = (1.0 - value)*0.5; - double p = t*(ASIN_PS0+t*(ASIN_PS1+t*(ASIN_PS2+t*(ASIN_PS3+t*(ASIN_PS4+t*ASIN_PS5))))); - double q = 1.0+t*(ASIN_QS1+t*(ASIN_QS2+t*(ASIN_QS3+t*ASIN_QS4))); - double s = sqrt(t); - double z = s+s*(p/q); - double result = ASIN_PIO2_HI-((z+z)-ASIN_PIO2_LO); - return negateResult ? -result : result; - } else { // value >= 1.0, or value is NaN - if (value == 1.0) { - return negateResult ? -Math.PI/2 : Math.PI/2; - } else { - return Double.NaN; - } - } - } - } - - /** - * If value is not NaN and is outside [-1,1] range, closest value in this range is used. - * - * @param value Value in [-1,1]. - * @return Value arcsine, in radians, in [-PI/2,PI/2]. - */ - public static double asinInRange(double value) { - if (value <= -1.0) { - return -Math.PI/2; - } else if (value >= 1.0) { - return Math.PI/2; - } else { - return asin(value); - } - } - - /** - * @param value Value in [-1,1]. - * @return Value arccosine, in radians, in [0,PI]. - */ - public static double acos(double value) { - if (USE_JDK_MATH) { - return Math.acos(value); - } - return Math.PI/2 - asin(value); - } - - /** - * If value is not NaN and is outside [-1,1] range, - * closest value in this range is used. - * - * @param value Value in [-1,1]. - * @return Value arccosine, in radians, in [0,PI]. - */ - public static double acosInRange(double value) { - if (value <= -1.0) { - return Math.PI; - } else if (value >= 1.0) { - return 0.0; - } else { - return acos(value); - } - } - - /** - * @param value A double value. - * @return Value arctangent, in radians, in [-PI/2,PI/2]. - */ - public static double atan(double value) { - if (USE_JDK_MATH) { - return Math.atan(value); - } - boolean negateResult = false; - if (value < 0.0) { - value = -value; - negateResult = true; - } - if (value == 1.0) { - // We want "exact" result for 1.0. - return negateResult ? -Math.PI/4 : Math.PI/4; - } else if (value <= ATAN_MAX_VALUE_FOR_TABS) { - int index = (int)(value * ATAN_INDEXER + 0.5); - double delta = value - index * ATAN_DELTA; - double result = MyTAtan.atanTab[index] - + delta * (MyTAtan.atanDer1DivF1Tab[index] - + delta * (MyTAtan.atanDer2DivF2Tab[index] - + delta * (MyTAtan.atanDer3DivF3Tab[index] - + delta * MyTAtan.atanDer4DivF4Tab[index]))); - return negateResult ? -result : result; - } else { // value > ATAN_MAX_VALUE_FOR_TABS, or value is NaN - // This part is derived from fdlibm. - if (value < TWO_POW_66) { - double x = -1/value; - double x2 = x*x; - double x4 = x2*x2; - double s1 = x2*(ATAN_AT0+x4*(ATAN_AT2+x4*(ATAN_AT4+x4*(ATAN_AT6+x4*(ATAN_AT8+x4*ATAN_AT10))))); - double s2 = x4*(ATAN_AT1+x4*(ATAN_AT3+x4*(ATAN_AT5+x4*(ATAN_AT7+x4*ATAN_AT9)))); - double result = ATAN_HI3-((x*(s1+s2)-ATAN_LO3)-x); - return negateResult ? -result : result; - } else { // value >= 2^66, or value is NaN - if (value != value) { - return Double.NaN; - } else { - return negateResult ? -Math.PI/2 : Math.PI/2; - } - } - } - } - - /** - * For special values for which multiple conventions could be adopted, - * behaves like Math.atan2(double,double). - * - * @param y Coordinate on y axis. - * @param x Coordinate on x axis. - * @return Angle from x axis positive side to (x,y) position, in radians, in [-PI,PI]. - * Angle measure is positive when going from x axis to y axis (positive sides). - */ - public static double atan2(double y, double x) { - if (USE_JDK_MATH) { - return Math.atan2(y,x); - } - /* - * Using sub-methods, to make method lighter for general case, - * and to avoid JIT-optimization crash on NaN. - */ - if (x > 0.0) { - if (y == 0.0) { - // +-0.0 - return y; - } - if (x == Double.POSITIVE_INFINITY) { - return atan2_pinf_yyy(y); - } else { - return atan(y/x); - } - } else if (x < 0.0) { - if (y == 0.0) { - return signFromBit(y) * Math.PI; - } - if (x == Double.NEGATIVE_INFINITY) { - return atan2_ninf_yyy(y); - } else if (y > 0.0) { - return Math.PI/2 - atan(x/y); - } else if (y < 0.0) { - return -Math.PI/2 - atan(x/y); - } else { - return Double.NaN; - } - } else { - return atan2_yyy_zeroOrNaN(y, x); - } - } - - /** - * Gives same result as Math.toRadians for some particular values - * like 90.0, 180.0 or 360.0, but is faster (no division). - * - * @param angdeg Angle value in degrees. - * @return Angle value in radians. - */ - public static double toRadians(double angdeg) { - if (USE_JDK_MATH) { - return Math.toRadians(angdeg); - } - return angdeg * (Math.PI/180); - } - - /** - * Gives same result as Math.toDegrees for some particular values - * like Math.PI/2, Math.PI or 2*Math.PI, but is faster (no division). - * - * @param angrad Angle value in radians. - * @return Angle value in degrees. - */ - public static double toDegrees(double angrad) { - if (USE_JDK_MATH) { - return Math.toDegrees(angrad); - } - return angrad * (180/Math.PI); - } - - /** - * @param sign Sign of the angle: true for positive, false for negative. - * @param degrees Degrees, in [0,180]. - * @param minutes Minutes, in [0,59]. - * @param seconds Seconds, in [0.0,60.0[. - * @return Angle in radians. - */ - public static double toRadians(boolean sign, int degrees, int minutes, double seconds) { - return toRadians(toDegrees(sign, degrees, minutes, seconds)); - } - - /** - * @param sign Sign of the angle: true for positive, false for negative. - * @param degrees Degrees, in [0,180]. - * @param minutes Minutes, in [0,59]. - * @param seconds Seconds, in [0.0,60.0[. - * @return Angle in degrees. - */ - public static double toDegrees(boolean sign, int degrees, int minutes, double seconds) { - double signFactor = sign ? 1.0 : -1.0; - return signFactor * (degrees + (1.0/60)*(minutes + (1.0/60)*seconds)); - } - - /** - * @param angrad Angle in radians. - * @param degrees (out) Degrees, in [0,180]. - * @param minutes (out) Minutes, in [0,59]. - * @param seconds (out) Seconds, in [0.0,60.0[. - * @return true if the resulting angle in [-180deg,180deg] is positive, false if it is negative. - */ - public static boolean toDMS(double angrad, IntWrapper degrees, IntWrapper minutes, DoubleWrapper seconds) { - // Computing longitude DMS. - double tmp = toDegrees(normalizeMinusPiPi(angrad)); - boolean isNeg = (tmp < 0.0); - if (isNeg) { - tmp = -tmp; - } - degrees.value = (int)tmp; - tmp = (tmp-degrees.value)*60.0; - minutes.value = (int)tmp; - seconds.value = Math.min((tmp-minutes.value)*60.0,DOUBLE_BEFORE_60); - return !isNeg; - } - - /** - * NB: Since 2*Math.PI < 2*PI, a span of 2*Math.PI does not mean full angular range. - * ex.: isInClockwiseDomain(0.0, 2*Math.PI, -1e-20) returns false. - * ---> For full angular range, use a span > 2*Math.PI, like 2*PI_SUP constant of this class. - * - * @param startAngRad An angle, in radians. - * @param angSpanRad An angular span, >= 0.0, in radians. - * @param angRad An angle, in radians. - * @return true if angRad is in the clockwise angular domain going from startAngRad, over angSpanRad, - * extremities included, false otherwise. - */ - public static boolean isInClockwiseDomain(double startAngRad, double angSpanRad, double angRad) { - if (Math.abs(angRad) < -TWO_MATH_PI_IN_MINUS_PI_PI) { - // special case for angular values of small magnitude - if (angSpanRad <= 2*Math.PI) { - if (angSpanRad < 0.0) { - // empty domain - return false; - } - // angSpanRad is in [0,2*PI] - startAngRad = normalizeMinusPiPi(startAngRad); - double endAngRad = normalizeMinusPiPi(startAngRad + angSpanRad); - if (startAngRad <= endAngRad) { - return (angRad >= startAngRad) && (angRad <= endAngRad); - } else { - return (angRad >= startAngRad) || (angRad <= endAngRad); - } - } else { // angSpanRad > 2*Math.PI, or is NaN - return (angSpanRad == angSpanRad); - } - } else { - // general case - return (normalizeZeroTwoPi(angRad - startAngRad) <= angSpanRad); - } - } - - /* - * hyperbolic trigonometry - */ - - /** - * Some properties of sinh(x) = (exp(x)-exp(-x))/2: - * 1) defined on ]-Infinity,+Infinity[ - * 2) result in ]-Infinity,+Infinity[ - * 3) sinh(x) = -sinh(-x) (implies sinh(0) = 0) - * 4) sinh(epsilon) ~= epsilon - * 5) lim(sinh(x),x->+Infinity) = +Infinity - * (y increasing exponentially faster than x) - * 6) reaches +Infinity (double overflow) for x >= 710.475860073944, - * i.e. a bit further than exp(x) - * - * @param value A double value. - * @return Value hyperbolic sine. - */ - public static double sinh(double value) { - if (USE_JDK_MATH) { - return Math.sinh(value); - } - // sinh(x) = (exp(x)-exp(-x))/2 - double h; - if (value < 0.0) { - value = -value; - h = -0.5; - } else { - h = 0.5; - } - if (value < 22.0) { - if (value < TWO_POW_N28) { - return (h < 0.0) ? -value : value; - } else { - // sinh(x) - // = (exp(x)-exp(-x))/2 - // = (exp(x)-1/exp(x))/2 - // = (expm1(x) + 1 - 1/(expm1(x)+1))/2 - // = (expm1(x) + (expm1(x)+1)/(expm1(x)+1) - 1/(expm1(x)+1))/2 - // = (expm1(x) + expm1(x)/(expm1(x)+1))/2 - double t = expm1(value); - // Might be more accurate, if value < 1: return h*((t+t)-t*t/(t+1.0)). - return h * (t + t/(t+1.0)); - } - } else if (value < LOG_DOUBLE_MAX_VALUE) { - return h * exp(value); - } else { - double t = exp(value*0.5); - return (h*t)*t; - } - } - - /** - * Some properties of cosh(x) = (exp(x)+exp(-x))/2: - * 1) defined on ]-Infinity,+Infinity[ - * 2) result in [1,+Infinity[ - * 3) cosh(0) = 1 - * 4) cosh(x) = cosh(-x) - * 5) lim(cosh(x),x->+Infinity) = +Infinity - * (y increasing exponentially faster than x) - * 6) reaches +Infinity (double overflow) for x >= 710.475860073944, - * i.e. a bit further than exp(x) - * - * @param value A double value. - * @return Value hyperbolic cosine. - */ - public static double cosh(double value) { - if (USE_JDK_MATH) { - return Math.cosh(value); - } - // cosh(x) = (exp(x)+exp(-x))/2 - if (value < 0.0) { - value = -value; - } - if (value < LOG_TWO_POW_27) { - if (value < TWO_POW_N27) { - // cosh(x) - // = (exp(x)+exp(-x))/2 - // = ((1+x+x^2/2!+...) + (1-x+x^2/2!-...))/2 - // = 1+x^2/2!+x^4/4!+... - // For value of x small in magnitude, the sum of the terms does not add to 1. - return 1; - } else { - // cosh(x) - // = (exp(x)+exp(-x))/2 - // = (exp(x)+1/exp(x))/2 - double t = exp(value); - return 0.5 * (t+1/t); - } - } else if (value < LOG_DOUBLE_MAX_VALUE) { - return 0.5 * exp(value); - } else { - double t = exp(value*0.5); - return (0.5*t)*t; - } - } - - /** - * Much more accurate than cosh(value)-1, - * for arguments (and results) close to zero. - * - * coshm1(-0.0) = -0.0, for homogeneity with - * acosh1p(-0.0) = -0.0. - * - * @param value A double value. - * @return Value hyperbolic cosine, minus 1. - */ - public static double coshm1(double value) { - // cosh(x)-1 = (exp(x)+exp(-x))/2 - 1 - if (value < 0.0) { - value = -value; - } - if (value < LOG_TWO_POW_27) { - if (value < TWO_POW_N27) { - if (value == 0.0) { - // +-0.0 - return value; - } - // Using (expm1(x)+expm1(-x))/2 - // is not accurate for tiny values, - // for expm1 results are of higher - // magnitude than the result and - // of different signs, such as their - // sum is not accurate. - // cosh(x) - 1 - // = (exp(x)+exp(-x))/2 - 1 - // = ((1+x+x^2/2!+...) + (1-x+x^2/2!-...))/2 - 1 - // = x^2/2!+x^4/4!+... - // ~= x^2 * (1/2 + x^2 * 1/24) - // = x^2 * 0.5 (since x < 2^-27) - return 0.5 * value*value; - } else { - // cosh(x) - 1 - // = (exp(x)+exp(-x))/2 - 1 - // = (exp(x)-1+exp(-x)-1)/2 - // = (expm1(x)+expm1(-x))/2 - return 0.5 * (expm1(value)+expm1(-value)); - } - } else if (value < LOG_DOUBLE_MAX_VALUE) { - return 0.5 * exp(value) - 1.0; - } else { - // No need to subtract 1 from result. - double t = exp(value*0.5); - return (0.5*t)*t; - } - } - - /** - * Computes hyperbolic sine and hyperbolic cosine together. - * - * @param value A double value. - * @param hcosine (out) Value hyperbolic cosine. - * @return Value hyperbolic sine. - */ - public static double sinhAndCosh(double value, DoubleWrapper hcosine) { - if (USE_JDK_MATH) { - hcosine.value = Math.cosh(value); - return Math.sinh(value); - } - // Mixup of sinh and cosh treatments: if you modify them, - // you might want to also modify this. - double h; - if (value < 0.0) { - value = -value; - h = -0.5; - } else { - h = 0.5; - } - final double hsine; - // LOG_TWO_POW_27 = 18.714973875118524 - if (value < LOG_TWO_POW_27) { // test from cosh - // sinh - if (value < TWO_POW_N28) { - hsine = (h < 0.0) ? -value : value; - } else { - double t = expm1(value); - hsine = h * (t + t/(t+1.0)); - } - // cosh - if (value < TWO_POW_N27) { - hcosine.value = 1; - } else { - double t = exp(value); - hcosine.value = 0.5 * (t+1/t); - } - } else if (value < 22.0) { // test from sinh - // Here, value is in [18.714973875118524,22.0[. - double t = expm1(value); - hsine = h * (t + t/(t+1.0)); - hcosine.value = 0.5 * (t+1.0); - } else { - if (value < LOG_DOUBLE_MAX_VALUE) { - hsine = h * exp(value); - } else { - double t = exp(value*0.5); - hsine = (h*t)*t; - } - hcosine.value = Math.abs(hsine); - } - return hsine; - } - - /** - * Some properties of tanh(x) = sinh(x)/cosh(x) = (exp(2*x)-1)/(exp(2*x)+1): - * 1) defined on ]-Infinity,+Infinity[ - * 2) result in ]-1,1[ - * 3) tanh(x) = -tanh(-x) (implies tanh(0) = 0) - * 4) tanh(epsilon) ~= epsilon - * 5) lim(tanh(x),x->+Infinity) = 1 - * 6) reaches 1 (double loss of precision) for x = 19.061547465398498 - * - * @param value A double value. - * @return Value hyperbolic tangent. - */ - public static double tanh(double value) { - if (USE_JDK_MATH) { - return Math.tanh(value); - } - // tanh(x) = sinh(x)/cosh(x) - // = (exp(x)-exp(-x))/(exp(x)+exp(-x)) - // = (exp(2*x)-1)/(exp(2*x)+1) - boolean negateResult = false; - if (value < 0.0) { - value = -value; - negateResult = true; - } - double z; - if (value < TANH_1_THRESHOLD) { - if (value < TWO_POW_N55) { - return negateResult ? -value*(1.0-value) : value*(1.0+value); - } else if (value >= 1) { - z = 1.0-2.0/(expm1(value+value)+2.0); - } else { - double t = expm1(-(value+value)); - z = -t/(t+2.0); - } - } else { - z = (value != value) ? Double.NaN : 1.0; - } - return negateResult ? -z : z; - } - - /** - * Some properties of asinh(x) = log(x + sqrt(x^2 + 1)) - * 1) defined on ]-Infinity,+Infinity[ - * 2) result in ]-Infinity,+Infinity[ - * 3) asinh(x) = -asinh(-x) (implies asinh(0) = 0) - * 4) asinh(epsilon) ~= epsilon - * 5) lim(asinh(x),x->+Infinity) = +Infinity - * (y increasing logarithmically slower than x) - * - * @param value A double value. - * @return Value hyperbolic arcsine. - */ - public static double asinh(double value) { - // asinh(x) = log(x + sqrt(x^2 + 1)) - boolean negateResult = false; - if (value < 0.0) { - value = -value; - negateResult = true; - } - double result; - // (about) smallest possible for - // non-log1p case to be accurate. - if (value < ASINH_LOG1P_THRESHOLD) { - // Around this range, FDLIBM uses - // log1p(value+value*value/(1+sqrt(value*value+1))), - // but it's slower, so we don't use it. - /* - * If x is close to zero, log argument is close to 1, - * so to avoid precision loss we use log1p(double), - * with - * (1+x)^p = 1 + p * x + (p*(p-1))/2! * x^2 + (p*(p-1)*(p-2))/3! * x^3 + ... - * (1+x)^p = 1 + p * x * (1 + (p-1)/2 * x * (1 + (p-2)/3 * x + ...) - * (1+x)^0.5 = 1 + 0.5 * x * (1 + (0.5-1)/2 * x * (1 + (0.5-2)/3 * x + ...) - * (1+x^2)^0.5 = 1 + 0.5 * x^2 * (1 + (0.5-1)/2 * x^2 * (1 + (0.5-2)/3 * x^2 + ...) - * x + (1+x^2)^0.5 = 1 + x * (1 + 0.5 * x * (1 + (0.5-1)/2 * x^2 * (1 + (0.5-2)/3 * x^2 + ...)) - * so - * asinh(x) = log1p(x * (1 + 0.5 * x * (1 + (0.5-1)/2 * x^2 * (1 + (0.5-2)/3 * x^2 + ...))) - */ - final double x = value; - final double x2 = x*x; - // Enough terms for good accuracy, - // given our threshold. - final double argLog1p = (x * - (1 + 0.5 * x - * (1 + (0.5-1)/2 * x2 - * (1 + (0.5-2)/3 * x2 - * (1 + (0.5-3)/4 * x2 - * (1 + (0.5-4)/5 * x2 - )))))); - result = log1p(argLog1p); - } else if (value < ASINH_ACOSH_SQRT_ELISION_THRESHOLD) { - // Around this range, FDLIBM uses - // log(2*value+1/(value+sqrt(value*value+1))), - // but it involves an additional division - // so we don't use it. - result = log(value + sqrt(value*value + 1.0)); - } else { - // log(2*value) would overflow for value > Double.MAX_VALUE/2, - // so we compute otherwise. - result = LOG_2 + log(value); - } - return negateResult ? -result : result; - } - - /** - * Some properties of acosh(x) = log(x + sqrt(x^2 - 1)): - * 1) defined on [1,+Infinity[ - * 2) result in ]0,+Infinity[ (by convention, since cosh(x) = cosh(-x)) - * 3) acosh(1) = 0 - * 4) acosh(1+epsilon) ~= log(1 + sqrt(2*epsilon)) ~= sqrt(2*epsilon) - * 5) lim(acosh(x),x->+Infinity) = +Infinity - * (y increasing logarithmically slower than x) - * - * @param value A double value. - * @return Value hyperbolic arccosine. - */ - public static double acosh(double value) { - if (!(value > 1.0)) { - // NaN, or value <= 1 - if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { - return (value < 1.0) ? Double.NaN : value - 1.0; - } else { - return (value == 1.0) ? 0.0 : Double.NaN; - } - } - double result; - if (value < ASINH_ACOSH_SQRT_ELISION_THRESHOLD) { - // Around this range, FDLIBM uses - // log(2*value-1/(value+sqrt(value*value-1))), - // but it involves an additional division - // so we don't use it. - result = log(value + sqrt(value*value - 1.0)); - } else { - // log(2*value) would overflow for value > Double.MAX_VALUE/2, - // so we compute otherwise. - result = LOG_2 + log(value); - } - return result; - } - - /** - * Much more accurate than acosh(1+value), - * for arguments (and results) close to zero. - * - * acosh1p(-0.0) = -0.0, for homogeneity with - * sqrt(-0.0) = -0.0, which looks about the same - * near 0. - * - * @param value A double value. - * @return Hyperbolic arccosine of (1+value). - */ - public static double acosh1p(double value) { - if (!(value > 0.0)) { - // NaN, or value <= 0. - // If value is -0.0, returning -0.0. - if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { - return (value < 0.0) ? Double.NaN : value; - } else { - return (value == 0.0) ? value : Double.NaN; - } - } - double result; - if (value < (ASINH_ACOSH_SQRT_ELISION_THRESHOLD-1)) { - // acosh(1+x) - // = log((1+x) + sqrt((1+x)^2 - 1)) - // = log(1 + x + sqrt(1 + 2*x + x^2 - 1)) - // = log1p(x + sqrt(2*x + x^2)) - // = log1p(x + sqrt(x * (2 + x)) - result = log1p(value + sqrt(value * (2 + value))); - } else { - result = LOG_2 + log(1+value); - } - return result; - } - - /** - * Some properties of atanh(x) = log((1+x)/(1-x))/2: - * 1) defined on ]-1,1[ - * 2) result in ]-Infinity,+Infinity[ - * 3) atanh(-1) = -Infinity (by continuity) - * 4) atanh(1) = +Infinity (by continuity) - * 5) atanh(epsilon) ~= epsilon - * 6) lim(atanh(x),x->1) = +Infinity - * - * @param value A double value. - * @return Value hyperbolic arctangent. - */ - public static double atanh(double value) { - boolean negateResult = false; - if (value < 0.0) { - value = -value; - negateResult = true; - } - double result; - if (!(value < 1.0)) { - // NaN, or value >= 1 - if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { - result = (value > 1.0) ? Double.NaN : Double.POSITIVE_INFINITY + value; - } else { - result = (value == 1.0) ? Double.POSITIVE_INFINITY : Double.NaN; - } - } else { - // For value < 0.5, FDLIBM uses - // 0.5 * log1p((value+value) + (value+value)*value/(1-value)), - // instead, but this is good enough for us. - // atanh(x) - // = log((1+x)/(1-x))/2 - // = log((1-x+2x)/(1-x))/2 - // = log1p(2x/(1-x))/2 - result = 0.5 * log1p((value+value)/(1.0-value)); - } - return negateResult ? -result : result; - } - - /* - * exponentials - */ - - /** - * @param value A double value. - * @return e^value. - */ - public static double exp(double value) { - if (USE_JDK_MATH) { - return Math.exp(value); - } - // exp(x) = exp([x])*exp(y) - // with [x] the integer part of x, and y = x-[x] - // ===> - // We find an approximation of y, called z. - // ===> - // exp(x) = exp([x])*(exp(z)*exp(epsilon)) - // with epsilon = y - z - // ===> - // We have exp([x]) and exp(z) pre-computed in tables, we "just" have to compute exp(epsilon). - // - // We use the same indexing (cast to int) to compute x integer part and the - // table index corresponding to z, to avoid two int casts. - // Also, to optimize index multiplication and division, we use powers of two, - // so that we can do it with bits shifts. - - if (value > EXP_OVERFLOW_LIMIT) { - return Double.POSITIVE_INFINITY; - } else if (!(value >= EXP_UNDERFLOW_LIMIT)) { - return (value != value) ? Double.NaN : 0.0; - } - - final int indexes = (int)(value*EXP_LO_INDEXING); - - final int valueInt; - if (indexes >= 0) { - valueInt = (indexes>>EXP_LO_INDEXING_DIV_SHIFT); - } else { - valueInt = -((-indexes)>>EXP_LO_INDEXING_DIV_SHIFT); - } - final double hiTerm = MyTExp.expHiTab[valueInt-(int)EXP_UNDERFLOW_LIMIT]; - - final int zIndex = indexes - (valueInt< 0.0) { - if (value == Double.POSITIVE_INFINITY) { - return Double.POSITIVE_INFINITY; - } - - // For normal values not close to 1.0, we use the following formula: - // log(value) - // = log(2^exponent*1.mantissa) - // = log(2^exponent) + log(1.mantissa) - // = exponent * log(2) + log(1.mantissa) - // = exponent * log(2) + log(1.mantissaApprox) + log(1.mantissa/1.mantissaApprox) - // = exponent * log(2) + log(1.mantissaApprox) + log(1+epsilon) - // = exponent * log(2) + log(1.mantissaApprox) + epsilon-epsilon^2/2+epsilon^3/3-epsilon^4/4+... - // with: - // 1.mantissaApprox <= 1.mantissa, - // log(1.mantissaApprox) in table, - // epsilon = (1.mantissa/1.mantissaApprox)-1 - // - // To avoid bad relative error for small results, - // values close to 1.0 are treated aside, with the formula: - // log(x) = z*(2+z^2*((2.0/3)+z^2*((2.0/5))+z^2*((2.0/7))+...))) - // with z=(x-1)/(x+1) - - double h; - if (value > 0.95) { - if (value < 1.14) { - double z = (value-1.0)/(value+1.0); - double z2 = z*z; - return z*(2+z2*((2.0/3)+z2*((2.0/5)+z2*((2.0/7)+z2*((2.0/9)+z2*((2.0/11))))))); - } - h = 0.0; - } else if (value < DOUBLE_MIN_NORMAL) { - // Ensuring value is normal. - value *= TWO_POW_52; - // log(x*2^52) - // = log(x)-ln(2^52) - // = log(x)-52*ln(2) - h = -52*LOG_2; - } else { - h = 0.0; - } - - int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); - int valueExp = (valueBitsHi>>20)-MAX_DOUBLE_EXPONENT; - // Getting the first LOG_BITS bits of the mantissa. - int xIndex = ((valueBitsHi<<12)>>>(32-LOG_BITS)); - - // 1.mantissa/1.mantissaApprox - 1 - double z = (value * twoPowNormalOrSubnormal(-valueExp)) * MyTLog.logXInvTab[xIndex] - 1; - - z *= (1-z*((1.0/2)-z*((1.0/3)))); - - return h + valueExp * LOG_2 + (MyTLog.logXLogTab[xIndex] + z); - - } else if (value == 0.0) { - return Double.NEGATIVE_INFINITY; - } else { // value < 0.0, or value is NaN - return Double.NaN; - } - } - - /** - * Quick log, with a max relative error of about 1.9e-3 - * for values in ]Double.MIN_NORMAL,+Infinity[, and - * worse accuracy outside this range. - * - * @param value A double value, in ]0,+Infinity[ (strictly positive and finite). - * @return Value logarithm (base e). - */ - public static double logQuick(double value) { - if (USE_JDK_MATH) { - return Math.log(value); - } - /* - * Inverse of Schraudolph's method for exp, is very inaccurate near 1, - * and not that fast (even using floats), especially with added if's - * to deal with values near 1, so we don't use it, and use a simplified - * version of our log's redefined algorithm. - */ - - // Simplified version of log's redefined algorithm: - // log(value) ~= exponent * log(2) + log(1.mantissaApprox) - - double h; - if (value > 0.87) { - if (value < 1.16) { - return 2.0 * (value-1.0)/(value+1.0); - } - h = 0.0; - } else if (value < DOUBLE_MIN_NORMAL) { - value *= TWO_POW_52; - h = -52*LOG_2; - } else { - h = 0.0; - } - - int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); - int valueExp = (valueBitsHi>>20)-MAX_DOUBLE_EXPONENT; - int xIndex = ((valueBitsHi<<12)>>>(32-LOG_BITS)); - - return h + valueExp * LOG_2 + MyTLog.logXLogTab[xIndex]; - } - - /** - * @param value A double value. - * @return Value logarithm (base 10). - */ - public static double log10(double value) { - if (USE_JDK_MATH || (!USE_REDEFINED_LOG)) { - return Math.log10(value); - } - // INV_LOG_10 is < 1, but there is no risk of log(double) - // overflow (positive or negative) while the end result shouldn't, - // since log(Double.MIN_VALUE) and log(Double.MAX_VALUE) have - // magnitudes of just a few hundreds. - return log(value) * INV_LOG_10; - } - - /** - * Much more accurate than log(1+value), - * for arguments (and results) close to zero. - * - * @param value A double value. - * @return Logarithm (base e) of (1+value). - */ - public static double log1p(double value) { - if (USE_JDK_MATH) { - return Math.log1p(value); - } - if (false) { - // This also works. Simpler but a bit slower. - if (value == Double.POSITIVE_INFINITY) { - return Double.POSITIVE_INFINITY; - } - double valuePlusOne = 1+value; - if (valuePlusOne == 1.0) { - return value; - } else { - return log(valuePlusOne)*(value/(valuePlusOne-1.0)); - } - } - if (value > -1.0) { - if (value == Double.POSITIVE_INFINITY) { - return Double.POSITIVE_INFINITY; - } - - // ln'(x) = 1/x - // so - // log(x+epsilon) ~= log(x) + epsilon/x - // - // Let u be 1+value rounded: - // 1+value = u+epsilon - // - // log(1+value) - // = log(u+epsilon) - // ~= log(u) + epsilon/value - // We compute log(u) as done in log(double), and then add the corrective term. - - double valuePlusOne = 1.0+value; - if (valuePlusOne == 1.0) { - return value; - } else if (Math.abs(value) < 0.15) { - double z = value/(value+2.0); - double z2 = z*z; - return z*(2+z2*((2.0/3)+z2*((2.0/5)+z2*((2.0/7)+z2*((2.0/9)+z2*((2.0/11))))))); - } - - int valuePlusOneBitsHi = (int)(Double.doubleToRawLongBits(valuePlusOne)>>32) & 0x7FFFFFFF; - int valuePlusOneExp = (valuePlusOneBitsHi>>20)-MAX_DOUBLE_EXPONENT; - // Getting the first LOG_BITS bits of the mantissa. - int xIndex = ((valuePlusOneBitsHi<<12)>>>(32-LOG_BITS)); - - // 1.mantissa/1.mantissaApprox - 1 - double z = (valuePlusOne * twoPowNormalOrSubnormal(-valuePlusOneExp)) * MyTLog.logXInvTab[xIndex] - 1; - - z *= (1-z*((1.0/2)-z*(1.0/3))); - - // Adding epsilon/valuePlusOne to z, - // with - // epsilon = value - (valuePlusOne-1) - // (valuePlusOne + epsilon ~= 1+value (not rounded)) - - return valuePlusOneExp * LOG_2 + MyTLog.logXLogTab[xIndex] + (z + (value - (valuePlusOne-1))/valuePlusOne); - } else if (value == -1.0) { - return Double.NEGATIVE_INFINITY; - } else { // value < -1.0, or value is NaN - return Double.NaN; - } - } - - /* - * powers - */ - - /** - * 1e-13ish accuracy or better on whole double range. - * - * @param value A double value. - * @param power A power. - * @return value^power. - */ - public static double pow(double value, double power) { - if (USE_JDK_MATH) { - return Math.pow(value,power); - } - if (power == 0.0) { - return 1.0; - } else if (power == 1.0) { - return value; - } - if (value <= 0.0) { - // powerInfo: 0 if not integer, 1 if even integer, -1 if odd integer - int powerInfo; - if (Math.abs(power) >= (TWO_POW_52*2)) { - // The binary digit just before comma is outside mantissa, - // thus it is always 0: power is an even integer. - powerInfo = 1; - } else { - // If power's magnitude permits, we cast into int instead of into long, - // as it is faster. - if (Math.abs(power) <= (double)Integer.MAX_VALUE) { - int powerAsInt = (int)power; - if (power == (double)powerAsInt) { - powerInfo = ((powerAsInt & 1) == 0) ? 1 : -1; - } else { // power is not an integer (and not NaN, due to test against Integer.MAX_VALUE) - powerInfo = 0; - } - } else { - long powerAsLong = (long)power; - if (power == (double)powerAsLong) { - powerInfo = ((powerAsLong & 1) == 0) ? 1 : -1; - } else { // power is not an integer, or is NaN - if (power != power) { - return Double.NaN; - } - powerInfo = 0; - } - } - } - - if (value == 0.0) { - if (power < 0.0) { - return (powerInfo < 0) ? 1/value : Double.POSITIVE_INFINITY; - } else { // power > 0.0 (0 and NaN cases already treated) - return (powerInfo < 0) ? value : 0.0; - } - } else { // value < 0.0 - if (value == Double.NEGATIVE_INFINITY) { - if (powerInfo < 0) { // power odd integer - return (power < 0.0) ? -0.0 : Double.NEGATIVE_INFINITY; - } else { // power even integer, or not an integer - return (power < 0.0) ? 0.0 : Double.POSITIVE_INFINITY; - } - } else { - return (powerInfo == 0) ? Double.NaN : powerInfo * exp(power*log(-value)); - } - } - } else { // value > 0.0, or value is NaN - return exp(power*log(value)); - } - } - - /** - * Quick pow, with a max relative error of about 1e-2 - * for value >= Double.MIN_NORMAL and 1e-10 < |value^power| < 1e10, - * of about 6e-2 for value >= Double.MIN_NORMAL and 1e-40 < |value^power| < 1e40, - * and worse accuracy otherwise. - * - * @param value A double value, in ]0,+Infinity[ (strictly positive and finite). - * @param power A double value. - * @return value^power. - */ - public static double powQuick(double value, double power) { - if (USE_JDK_MATH) { - return Math.pow(value,power); - } - return exp(power*logQuick(value)); - } - - /** - * This treatment is somehow accurate for low values of |power|, - * and for |power*getExponent(value)| < 1023 or so (to stay away - * from double extreme magnitudes (large and small)). - * - * @param value A double value. - * @param power A power. - * @return value^power. - */ - public static double powFast(double value, int power) { - if (USE_JDK_MATH) { - return Math.pow(value,power); - } - if (power < 3) { - if (power < 0) { - // Opposite of Integer.MIN_VALUE does not exist as int. - if (power == Integer.MIN_VALUE) { - // Integer.MAX_VALUE = -(power+1) - return 1.0/(powFast(value,Integer.MAX_VALUE) * value); - } else { - return 1.0/powFast(value,-power); - } - } else { - // Here, power is in [0,2]. - if (power == 2) { // Most common case first. - return value * value; - } else if (power == 0) { - return 1.0; - } else { // power == 1 - return value; - } - } - } else { // power >= 4 - double oddRemains = 1.0; - // If power <= 5, faster to finish outside the loop. - while (power > 5) { - // Test if power is odd. - if ((power & 1) != 0) { - oddRemains *= value; - } - value *= value; - power >>= 1; // power = power / 2 - } - // Here, power is in [3,5]. - if (power == 3) { - return oddRemains * value * value * value; - } else { // power in [4,5]. - double v2 = value * value; - if (power == 4) { - return oddRemains * v2 * v2; - } else { // power == 5 - return oddRemains * v2 * v2 * value; - } - } - } - } - - /** - * @param value A float value. - * @return value*value. - */ - public static float pow2(float value) { - return value*value; - } - - /** - * @param value A double value. - * @return value*value. - */ - public static double pow2(double value) { - return value*value; - } - - /** - * @param value A float value. - * @return value*value*value. - */ - public static float pow3(float value) { - return value*value*value; - } - - /** - * @param value A double value. - * @return value*value*value. - */ - public static double pow3(double value) { - return value*value*value; - } - - /* - * roots - */ - - /** - * @param value A double value. - * @return Value square root. - */ - public static double sqrt(double value) { - if (USE_JDK_MATH || (!USE_REDEFINED_SQRT)) { - return Math.sqrt(value); - } - // See cbrt for comments, sqrt uses the same ideas. - - if (!(value > 0.0)) { // value <= 0.0, or value is NaN - if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { - return (value < 0.0) ? Double.NaN : value; - } else { - return (value == 0.0) ? value : Double.NaN; - } - } else if (value == Double.POSITIVE_INFINITY) { - return Double.POSITIVE_INFINITY; - } - - double h; - if (value < DOUBLE_MIN_NORMAL) { - value *= TWO_POW_52; - h = 2*TWO_POW_N26; - } else { - h = 2.0; - } - - int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); - int valueExponentIndex = (valueBitsHi>>20)+(-MAX_DOUBLE_EXPONENT-MIN_DOUBLE_EXPONENT); - int xIndex = ((valueBitsHi<<12)>>>(32-SQRT_LO_BITS)); - - double result = MyTSqrt.sqrtXSqrtHiTab[valueExponentIndex] * MyTSqrt.sqrtXSqrtLoTab[xIndex]; - double slope = MyTSqrt.sqrtSlopeHiTab[valueExponentIndex] * MyTSqrt.sqrtSlopeLoTab[xIndex]; - value *= 0.25; - - result += (value - result * result) * slope; - result += (value - result * result) * slope; - return h*(result + (value - result * result) * slope); - } - - /** - * Quick sqrt, with with a max relative error of about 3.41e-2 - * for values in [Double.MIN_NORMAL,Double.MAX_VALUE], and worse - * accuracy outside this range. - * - * @param value A double value. - * @return Value square root. - */ - public static double sqrtQuick(double value) { - if (USE_JDK_MATH) { - return Math.sqrt(value); - } - final long bits = Double.doubleToRawLongBits(value); - /* - * Constant determined empirically, using a random-based metaheuristic. - * Should be possible to find a better one. - */ - return Double.longBitsToDouble((bits+4606859074900000000L)>>>1); - } - - /** - * Quick inverse of square root, with a max relative error of about 3.44e-2 - * for values in [Double.MIN_NORMAL,Double.MAX_VALUE], and worse accuracy - * outside this range. - * - * This implementation uses zero step of Newton's method. - * Here are the max relative errors on [Double.MIN_NORMAL,Double.MAX_VALUE] - * depending on number of steps, if you want to copy-paste this code - * and use your own number: - * n=0: about 3.44e-2 - * n=1: about 1.75e-3 - * n=2: about 4.6e-6 - * n=3: about 3.17e-11 - * n=4: about 3.92e-16 - * n=5: about 3.03e-16 - * - * @param value A double value. - * @return Inverse of value square root. - */ - public static double invSqrtQuick(double value) { - if (USE_JDK_MATH) { - return 1/Math.sqrt(value); - } - /* - * http://en.wikipedia.org/wiki/Fast_inverse_square_root - */ - if (false) { - // With one Newton step (much slower than - // 1/Math.sqrt(double) if not optimized). - final double halfInitial = value * 0.5; - long bits = Double.doubleToRawLongBits(value); - // If n=0, 6910474759270000000L might be better (3.38e-2 max relative error). - bits = 0x5FE6EB50C7B537A9L - (bits>>1); - value = Double.longBitsToDouble(bits); - value = value * (1.5 - halfInitial * value * value); // Newton step, can repeat. - return value; - } else { - return Double.longBitsToDouble(0x5FE6EB50C7B537A9L - (Double.doubleToRawLongBits(value)>>1)); - } - } - - /** - * @param value A double value. - * @return Value cubic root. - */ - public static double cbrt(double value) { - if (USE_JDK_MATH) { - return Math.cbrt(value); - } - double h; - if (value < 0.0) { - if (value == Double.NEGATIVE_INFINITY) { - return Double.NEGATIVE_INFINITY; - } - value = -value; - // Making sure value is normal. - if (value < DOUBLE_MIN_NORMAL) { - value *= (TWO_POW_52*TWO_POW_26); - // h = * / - h = -2*TWO_POW_N26; - } else { - h = -2.0; - } - } else { - if (!(value < Double.POSITIVE_INFINITY)) { // value is +Infinity, or value is NaN - return value; - } - // Making sure value is normal. - if (value < DOUBLE_MIN_NORMAL) { - if (value == 0.0) { - // cbrt(0.0) = 0.0, cbrt(-0.0) = -0.0 - return value; - } - value *= (TWO_POW_52*TWO_POW_26); - h = 2*TWO_POW_N26; - } else { - h = 2.0; - } - } - - // Normal value is (2^ * ). - // First member cubic root is computed, and multiplied with an approximation - // of the cubic root of the second member, to end up with a good guess of - // the result before using Newton's (or Archimedes's) method. - // To compute the cubic root approximation, we use the formula "cbrt(value) = cbrt(x) * cbrt(value/x)", - // choosing x as close to value as possible but inferior to it, so that cbrt(value/x) is close to 1 - // (we could iterate on this method, using value/x as new value for each iteration, - // but finishing with Newton's method is faster). - - // Shift and cast into an int, which overall is faster than working with a long. - int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); - int valueExponentIndex = (valueBitsHi>>20)+(-MAX_DOUBLE_EXPONENT-MIN_DOUBLE_EXPONENT); - // Getting the first CBRT_LO_BITS bits of the mantissa. - int xIndex = ((valueBitsHi<<12)>>>(32-CBRT_LO_BITS)); - double result = MyTCbrt.cbrtXCbrtHiTab[valueExponentIndex] * MyTCbrt.cbrtXCbrtLoTab[xIndex]; - double slope = MyTCbrt.cbrtSlopeHiTab[valueExponentIndex] * MyTCbrt.cbrtSlopeLoTab[xIndex]; - - // Lowering values to avoid overflows when using Newton's method - // (we will then just have to return twice the result). - // result^3 = value - // (result/2)^3 = value/8 - value *= 0.125; - // No need to divide result here, as division is factorized in result computation tables. - // result *= 0.5; - - // Newton's method, looking for y = x^(1/p): - // y(n) = y(n-1) + (x-y(n-1)^p) * slope(y(n-1)) - // y(n) = y(n-1) + (x-y(n-1)^p) * (1/p)*(x(n-1)^(1/p-1)) - // y(n) = y(n-1) + (x-y(n-1)^p) * (1/p)*(x(n-1)^((1-p)/p)) - // with x(n-1)=y(n-1)^p, i.e.: - // y(n) = y(n-1) + (x-y(n-1)^p) * (1/p)*(y(n-1)^(1-p)) - // - // For p=3: - // y(n) = y(n-1) + (x-y(n-1)^3) * (1/(3*y(n-1)^2)) - - // To save time, we don't recompute the slope between Newton's method steps, - // as initial slope is good enough for a few iterations. - // - // NB: slope = 1/(3*trueResult*trueResult) - // As we have result = trueResult/2 (to avoid overflows), we have: - // slope = 4/(3*result*result) - // = (4/3)*resultInv*resultInv - // with newResultInv = 1/newResult - // = 1/(oldResult+resultDelta) - // = (oldResultInv)*1/(1+resultDelta/oldResult) - // = (oldResultInv)*1/(1+resultDelta*oldResultInv) - // ~= (oldResultInv)*(1-resultDelta*oldResultInv) - // ===> Successive slopes could be computed without division, if needed, - // by computing resultInv (instead of slope right away) and retrieving - // slopes from it. - - result += (value - result * result * result) * slope; - result += (value - result * result * result) * slope; - return h*(result + (value - result * result * result) * slope); - } - - /** - * @return sqrt(x^2+y^2) without intermediate overflow or underflow. - */ - public static double hypot(double x, double y) { - if (USE_JDK_MATH) { - return Math.hypot(x,y); - } - x = Math.abs(x); - y = Math.abs(y); - // Ensuring x <= y. - if (y < x) { - double a = x; - x = y; - y = a; - } else if (!(y >= x)) { // Testing if we have some NaN. - return hypot_NaN(x, y); - } - - if (y-x == y) { - // x too small to subtract from y. - return y; - } else { - double factor; - if (y > HYPOT_MAX_MAG) { - // y is too large: scaling down. - x *= (1/HYPOT_FACTOR); - y *= (1/HYPOT_FACTOR); - factor = HYPOT_FACTOR; - } else if (x < (1/HYPOT_MAX_MAG)) { - // x is too small: scaling up. - x *= HYPOT_FACTOR; - y *= HYPOT_FACTOR; - factor = (1/HYPOT_FACTOR); - } else { - factor = 1.0; - } - return factor * sqrt(x*x+y*y); - } - } - - /** - * @return sqrt(x^2+y^2+z^2) without intermediate overflow or underflow. - */ - public static double hypot(double x, double y, double z) { - if (USE_JDK_MATH) { - // No simple JDK equivalent. - } - x = Math.abs(x); - y = Math.abs(y); - z = Math.abs(z); - /* - * Considering that z magnitude is the most likely to be the smaller, - * hence ensuring z <= y <= x, and not x <= y <= z, for less swaps. - */ - // Ensuring z <= y. - if (z > y) { - // y < z: swapping y and z - double a = z; - z = y; - y = a; - } else if (!(z <= y)) { // Testing if y or z is NaN. - return hypot_NaN(x, y, z); - } - // Ensuring y <= x. - if (z > x) { - // x < z <= y: moving x - double oldZ = z; - z = x; - double oldY = y; - y = oldZ; - x = oldY; - } else if (y > x) { - // z <= x < y: swapping x and y - double a = y; - y = x; - x = a; - } else if (x != x) { // Testing if x is NaN. - return hypot_NaN(x, y, z); - } - - if (x-y == x) { - // y, hence z, too small to subtract from x. - return x; - } else if (y-z == y) { - // z too small to subtract from y, hence x. - double factor; - if (x > HYPOT_MAX_MAG) { - // x is too large: scaling down. - x *= (1/HYPOT_FACTOR); - y *= (1/HYPOT_FACTOR); - factor = HYPOT_FACTOR; - } else if (y < (1/HYPOT_MAX_MAG)) { - // y is too small: scaling up. - x *= HYPOT_FACTOR; - y *= HYPOT_FACTOR; - factor = (1/HYPOT_FACTOR); - } else { - factor = 1.0; - } - return factor * sqrt(x*x+y*y); - } else { - double factor; - if (x > HYPOT_MAX_MAG) { - // x is too large: scaling down. - x *= (1/HYPOT_FACTOR); - y *= (1/HYPOT_FACTOR); - z *= (1/HYPOT_FACTOR); - factor = HYPOT_FACTOR; - } else if (z < (1/HYPOT_MAX_MAG)) { - // z is too small: scaling up. - x *= HYPOT_FACTOR; - y *= HYPOT_FACTOR; - z *= HYPOT_FACTOR; - factor = (1/HYPOT_FACTOR); - } else { - factor = 1.0; - } - // Adding smaller magnitudes together first. - return factor * sqrt(x*x+(y*y+z*z)); - } - } - - /* - * close values - */ - - /** - * @param value A float value. - * @return Floor of value. - */ - public static float floor(float value) { - final int exponent = getExponent(value); - if (exponent < 0) { - // abs(value) < 1. - if (value < 0.0f) { - return -1.0f; - } else { - // 0.0f, or -0.0f if value is -0.0f - return 0.0f * value; - } - } else if (exponent < 23) { - // A bit faster than using casts. - final int bits = Float.floatToRawIntBits(value); - final int anteCommaBits = bits & (0xFF800000>>exponent); - if ((value < 0.0f) && (anteCommaBits != bits)) { - return Float.intBitsToFloat(anteCommaBits) - 1.0f; - } else { - return Float.intBitsToFloat(anteCommaBits); - } - } else { - // +-Infinity, NaN, or a mathematical integer. - return value; - } - } - - /** - * @param value A double value. - * @return Floor of value. - */ - public static double floor(double value) { - if (USE_JDK_MATH) { - return Math.floor(value); - } - if (ANTI_SLOW_CASTS) { - double valueAbs = Math.abs(value); - if (valueAbs <= (double)Integer.MAX_VALUE) { - if (value > 0.0) { - return (double)(int)value; - } else if (value < 0.0) { - double anteCommaDigits = (double)(int)value; - if (value != anteCommaDigits) { - return anteCommaDigits - 1.0; - } else { - return anteCommaDigits; - } - } else { // value is +-0.0 (not NaN due to test against Integer.MAX_VALUE) - return value; - } - } else if (valueAbs < TWO_POW_52) { - // We split the value in two: - // high part, which is a mathematical integer, - // and the rest, for which we can get rid of the - // post comma digits by casting into an int. - double highPart = ((int)(value * TWO_POW_N26)) * TWO_POW_26; - if (value > 0.0) { - return highPart + (double)((int)(value - highPart)); - } else { - double anteCommaDigits = highPart + (double)((int)(value - highPart)); - if (value != anteCommaDigits) { - return anteCommaDigits - 1.0; - } else { - return anteCommaDigits; - } - } - } else { // abs(value) >= 2^52, or value is NaN - return value; - } - } else { - final int exponent = getExponent(value); - if (exponent < 0) { - // abs(value) < 1. - if (value < 0.0) { - return -1.0; - } else { - // 0.0, or -0.0 if value is -0.0 - return 0.0 * value; - } - } else if (exponent < 52) { - // A bit faster than working on bits. - final long matIntPart = (long)value; - final double matIntToValue = value-(double)matIntPart; - if (matIntToValue >= 0.0) { - return (double)matIntPart; - } else { - return (double)(matIntPart - 1); - } - } else { - // +-Infinity, NaN, or a mathematical integer. - return value; - } - } - } - - /** - * @param value A float value. - * @return Ceiling of value. - */ - public static float ceil(float value) { - return -floor(-value); - } - - /** - * @param value A double value. - * @return Ceiling of value. - */ - public static double ceil(double value) { - if (USE_JDK_MATH) { - return Math.ceil(value); - } - return -floor(-value); - } - - /** - * Might have different semantics than Math.round(float), - * see bugs 6430675 and 8010430. - * - * @param value A double value. - * @return Value rounded to nearest int, choosing superior int in case two - * are equally close (i.e. rounding-up). - */ - public static int round(float value) { - /* - * Not delegating to JDK, because we want delegation to provide - * at least as good results, and some supported JDK versions - * have bugged round() methods. - */ - // Algorithm by Dmitry Nadezhin (but replaced an if by a multiply) - // (http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-August/020247.html). - final int bits = Float.floatToRawIntBits(value); - final int biasedExp = ((bits>>23)&0xFF); - // Shift to get rid of bits past comma except first one: will need to - // 1-shift to the right to end up with correct magnitude. - final int shift = (23 - 1 + MAX_FLOAT_EXPONENT) - biasedExp; - if ((shift & -32) == 0) { - int bitsSignum = (((bits >> 31) << 1) + 1); - // shift in [0,31], so unbiased exp in [-9,22]. - int extendedMantissa = (0x00800000 | (bits & 0x007FFFFF)) * bitsSignum; - // If value is positive and first bit past comma is 0, rounding - // to lower integer, else to upper one, which is what "+1" and - // then ">>1" do. - return ((extendedMantissa >> shift) + 1) >> 1; - } else { - // +-Infinity, NaN, or a mathematical integer, or tiny. - if (false && ANTI_SLOW_CASTS) { // not worth it - if (Math.abs(value) >= -(float)Integer.MIN_VALUE) { - // +-Infinity or a mathematical integer (mostly) out of int range. - return (value < 0.0) ? Integer.MIN_VALUE : Integer.MAX_VALUE; - } - // NaN or a mathematical integer (mostly) in int range. - } - return (int)value; - } - } - - /** - * Might have different semantics than Math.round(double), - * see bugs 6430675 and 8010430. - * - * @param value A double value. - * @return Value rounded to nearest long, choosing superior long in case two - * are equally close (i.e. rounding-up). - */ - public static long round(double value) { - /* - * Not delegating to JDK, because we want delegation to provide - * at least as good results, and some supported JDK versions - * have bugged round() methods. - */ - final long bits = Double.doubleToRawLongBits(value); - final int biasedExp = (((int)(bits>>52))&0x7FF); - // Shift to get rid of bits past comma except first one: will need to - // 1-shift to the right to end up with correct magnitude. - final int shift = (52 - 1 + MAX_DOUBLE_EXPONENT) - biasedExp; - if ((shift & -64) == 0) { - long bitsSignum = (((bits >> 63) << 1) + 1); - // shift in [0,63], so unbiased exp in [-12,51]. - long extendedMantissa = (0x0010000000000000L | (bits & 0x000FFFFFFFFFFFFFL)) * bitsSignum; - // If value is positive and first bit past comma is 0, rounding - // to lower integer, else to upper one, which is what "+1" and - // then ">>1" do. - return ((extendedMantissa >> shift) + 1L) >> 1; - } else { - // +-Infinity, NaN, or a mathematical integer, or tiny. - if (ANTI_SLOW_CASTS) { - if (Math.abs(value) >= -(double)Long.MIN_VALUE) { - // +-Infinity or a mathematical integer (mostly) out of long range. - return (value < 0.0) ? Long.MIN_VALUE : Long.MAX_VALUE; - } - // NaN or a mathematical integer (mostly) in long range. - } - return (long)value; - } - } - - /** - * @param value A float value. - * @return Value rounded to nearest int, choosing even int in case two - * are equally close. - */ - public static int roundEven(float value) { - final int sign = signFromBit(value); - value = Math.abs(value); - if (ANTI_SLOW_CASTS) { - if (value < TWO_POW_23_F) { - // Getting rid of post-comma bits. - value = ((value + TWO_POW_23_F) - TWO_POW_23_F); - return sign * (int)value; - } else if (value < (float)Integer.MAX_VALUE) { // "<=" doesn't work, because of float precision - // value is in [-Integer.MAX_VALUE,Integer.MAX_VALUE] - return sign * (int)value; - } - } else { - if (value < TWO_POW_23_F) { - // Getting rid of post-comma bits. - value = ((value + TWO_POW_23_F) - TWO_POW_23_F); - } - } - return (int)(sign * value); - } - - /** - * @param value A double value. - * @return Value rounded to nearest long, choosing even long in case two - * are equally close. - */ - public static long roundEven(double value) { - final int sign = (int)signFromBit(value); - value = Math.abs(value); - if (value < TWO_POW_52) { - // Getting rid of post-comma bits. - value = ((value + TWO_POW_52) - TWO_POW_52); - } - if (ANTI_SLOW_CASTS) { - if (value <= (double)Integer.MAX_VALUE) { - // value is in [-Integer.MAX_VALUE,Integer.MAX_VALUE] - return sign * (int)value; - } - } - return (long)(sign * value); - } - - /** - * @param value A float value. - * @return The float mathematical integer closest to the specified value, - * choosing even one if two are equally close, or respectively - * NaN, +-Infinity or +-0.0f if the value is any of these. - */ - public static float rint(float value) { - final int sign = signFromBit(value); - value = Math.abs(value); - if (value < TWO_POW_23_F) { - // Getting rid of post-comma bits. - value = ((TWO_POW_23_F + value ) - TWO_POW_23_F); - } - // Restoring original sign. - return sign * value; - } - - /** - * @param value A double value. - * @return The double mathematical integer closest to the specified value, - * choosing even one if two are equally close, or respectively - * NaN, +-Infinity or +-0.0 if the value is any of these. - */ - public static double rint(double value) { - if (USE_JDK_MATH) { - return Math.rint(value); - } - final int sign = (int)signFromBit(value); - value = Math.abs(value); - if (value < TWO_POW_52) { - // Getting rid of post-comma bits. - value = ((TWO_POW_52 + value ) - TWO_POW_52); - } - // Restoring original sign. - return sign * value; - } - - /* - * close int values - * - * Never delegating to JDK for these methods, for we should always - * be faster and exact, and JDK doesn't exactly have such methods. - */ - - /** - * @param value A double value. - * @return Floor of value as int, or closest int if floor is out - * of int range, or 0 if value is NaN. - */ - public static int floorToInt(double value) { - int valueInt = (int) value; - if (value < 0.0) { - if (value == (double) valueInt) { - return valueInt; - } else { - if (valueInt == Integer.MIN_VALUE) { - return valueInt; - } else { - return valueInt - 1; - } - } - } else { // >= 0 or NaN. - return valueInt; - } - } - - /** - * @param value A double value. - * @return Ceiling of value as int, or closest int if ceiling is out - * of int range, or 0 if value is NaN. - */ - public static int ceilToInt(double value) { - int valueInt = (int) value; - if (value > 0.0) { - if (value == (double) valueInt) { - return valueInt; - } else { - if (valueInt == Integer.MAX_VALUE) { - return valueInt; - } else { - return valueInt + 1; - } - } - } else { // <= 0 or NaN. - return valueInt; - } - } - - /** - * @param value A double value. - * @return Value rounded to nearest int, choosing superior int in case two - * are equally close (i.e. rounding-up). - */ - public static int roundToInt(double value) { - /* - * We don't gain much by reimplementing rounding, except for - * pathologically large values, which should not be a common case - * when dealing with ints, so we just use round(double). - */ - return NumbersUtils.toInt(round(value)); - } - - /** - * @param value A double value. - * @return Value rounded to nearest int, choosing even int in case two - * are equally close. - */ - public static int roundEvenToInt(double value) { - final int sign = (int)signFromBit(value); - value = Math.abs(value); - /* - * Applying the post-comma bits removal logic even if value is out - * of int range, to avoid a test, for it doesn't mess up the result, - * and we want to optimize for the case of values in int range. - */ - value = ((value + TWO_POW_52) - TWO_POW_52); - return (int)(sign * value); - } - - /* - * ranges - */ - - /** - * @param min A float value. - * @param max A float value. - * @param value A float value. - * @return min if value < min, max if value > max, value otherwise. - */ - public static float toRange(float min, float max, float value) { - return NumbersUtils.toRange(min, max, value); - } - - /** - * @param min A double value. - * @param max A double value. - * @param value A double value. - * @return min if value < min, max if value > max, value otherwise. - */ - public static double toRange(double min, double max, double value) { - return NumbersUtils.toRange(min, max, value); - } - - /* - * binary operators (/,%) - */ - - /** - * Returns dividend - divisor * n, where n is the mathematical integer - * closest to dividend/divisor. - * If dividend/divisor is equally close to surrounding integers, - * we choose n to be the integer of smallest magnitude, which makes - * this treatment differ from Math.IEEEremainder(double,double), - * where n is chosen to be the even integer. - * Note that the choice of n is not done considering the double - * approximation of dividend/divisor, because it could cause - * result to be outside [-|divisor|/2,|divisor|/2] range. - * The practical effect is that if multiple results would be possible, - * we always choose the result that is the closest to (and has the same - * sign as) the dividend. - * Ex. : - * - for (-3.0,2.0), this method returns -1.0, - * whereas Math.IEEEremainder returns 1.0. - * - for (-5.0,2.0), both this method and Math.IEEEremainder return -1.0. - * - * If the remainder is zero, its sign is the same as the sign of the first argument. - * If either argument is NaN, or the first argument is infinite, - * or the second argument is positive zero or negative zero, - * then the result is NaN. - * If the first argument is finite and the second argument is - * infinite, then the result is the same as the first argument. - * - * NB: - * - Modulo operator (%) returns a value in ]-|divisor|,|divisor|[, - * which sign is the same as dividend. - * - As for modulo operator, the sign of the divisor has no effect on the result. - * - On some architecture, % operator has been observed to return NaN - * for some subnormal values of divisor, when dividend exponent is 1023, - * which impacts the correctness of this method. - * - * @param dividend Dividend. - * @param divisor Divisor. - * @return Remainder of dividend/divisor, i.e. a value in [-|divisor|/2,|divisor|/2]. - */ - public static double remainder(double dividend, double divisor) { - if (Double.isInfinite(divisor)) { - if (Double.isInfinite(dividend)) { - return Double.NaN; - } else { - return dividend; - } - } - double value = dividend % divisor; - if (Math.abs(value+value) > Math.abs(divisor)) { - return value + ((value > 0.0) ? -Math.abs(divisor) : Math.abs(divisor)); - } else { - return value; - } - } - - /** - * @param angle Angle in radians. - * @return The same angle, in radians, but in [-PI,PI]. - */ - public static double normalizeMinusPiPi(double angle) { - // Not modifying values in output range. - if ((angle >= -Math.PI) && (angle <= Math.PI)) { - return angle; - } - return remainderTwoPi(angle); - } - - /** - * Not accurate for large values. - * - * @param angle Angle in radians. - * @return The same angle, in radians, but in [-PI,PI]. - */ - public static double normalizeMinusPiPiFast(double angle) { - // Not modifying values in output range. - if ((angle >= -Math.PI) && (angle <= Math.PI)) { - return angle; - } - return remainderTwoPiFast(angle); - } - - /** - * @param angle Angle in radians. - * @return The same angle, in radians, but in [0,2*PI]. - */ - public static double normalizeZeroTwoPi(double angle) { - // Not modifying values in output range. - if ((angle >= 0.0) && (angle <= 2*Math.PI)) { - return angle; - } - angle = remainderTwoPi(angle); - if (angle < 0.0) { - // LO then HI is theoretically better (when starting near 0). - return (angle + TWOPI_LO) + TWOPI_HI; - } else { - return angle; - } - } - - /** - * Not accurate for large values. - * - * @param angle Angle in radians. - * @return The same angle, in radians, but in [0,2*PI]. - */ - public static double normalizeZeroTwoPiFast(double angle) { - // Not modifying values in output range. - if ((angle >= 0.0) && (angle <= 2*Math.PI)) { - return angle; - } - angle = remainderTwoPiFast(angle); - if (angle < 0.0) { - // LO then HI is theoretically better (when starting near 0). - return (angle + TWOPI_LO) + TWOPI_HI; - } else { - return angle; - } - } - - /** - * @param angle Angle in radians. - * @return Angle value modulo PI, in radians, in [-PI/2,PI/2]. - */ - public static double normalizeMinusHalfPiHalfPi(double angle) { - // Not modifying values in output range. - if ((angle >= -Math.PI/2) && (angle <= Math.PI/2)) { - return angle; - } - return remainderPi(angle); - } - - /** - * Not accurate for large values. - * - * @param angle Angle in radians. - * @return Angle value modulo PI, in radians, in [-PI/2,PI/2]. - */ - public static double normalizeMinusHalfPiHalfPiFast(double angle) { - // Not modifying values in output range. - if ((angle >= -Math.PI/2) && (angle <= Math.PI/2)) { - return angle; - } - return remainderPiFast(angle); - } - - /* - * floating points utils - */ - - /** - * @param value A float value. - * @return true if the specified value is NaN or +-Infinity, false otherwise. - */ - public static boolean isNaNOrInfinite(float value) { - return NumbersUtils.isNaNOrInfinite(value); - } - - /** - * @param value A double value. - * @return true if the specified value is NaN or +-Infinity, false otherwise. - */ - public static boolean isNaNOrInfinite(double value) { - return NumbersUtils.isNaNOrInfinite(value); - } - - /** - * @param value A float value. - * @return Value unbiased exponent. - */ - public static int getExponent(float value) { - return ((Float.floatToRawIntBits(value)>>23)&0xFF)-MAX_FLOAT_EXPONENT; - } - - /** - * @param value A double value. - * @return Value unbiased exponent. - */ - public static int getExponent(double value) { - return (((int)(Double.doubleToRawLongBits(value)>>52))&0x7FF)-MAX_DOUBLE_EXPONENT; - } - - /** - * @param value A float value. - * @return -1.0f if the specified value is < 0, 1.0f if it is > 0, - * and the value itself if it is NaN or +-0.0f. - */ - public static float signum(float value) { - if (USE_JDK_MATH) { - return Math.signum(value); - } - if ((value == 0.0f) || (value != value)) { - return value; - } - return (float)signFromBit(value); - } - - /** - * @param value A double value. - * @return -1.0 if the specified value is < 0, 1.0 if it is > 0, - * and the value itself if it is NaN or +-0.0. - */ - public static double signum(double value) { - if (USE_JDK_MATH) { - return Math.signum(value); - } - if ((value == 0.0) || (value != value)) { - return value; - } - if (ANTI_SLOW_CASTS) { - return (double)(int)signFromBit(value); - } else { - return (double)signFromBit(value); - } - } - - /** - * @param value A float value. - * @return -1 if sign bit is 1, 1 if sign bit is 0. - */ - public static int signFromBit(float value) { - return ((Float.floatToRawIntBits(value)>>30)|1); - } - - /** - * @param value A double value. - * @return -1 if sign bit is 1, 1 if sign bit is 0. - */ - public static long signFromBit(double value) { - // Returning a long, to avoid useless cast into int. - return ((Double.doubleToRawLongBits(value)>>62)|1); - } - - /** - * A sign of NaN can be interpreted as positive or negative. - * - * @param magnitude A float value. - * @param sign A float value. - * @return A value with the magnitude of the first argument, and the sign - * of the second argument. - */ - public static float copySign(float magnitude, float sign) { - return Float.intBitsToFloat( - (Float.floatToRawIntBits(sign) & Integer.MIN_VALUE) - | (Float.floatToRawIntBits(magnitude) & Integer.MAX_VALUE)); - } - - /** - * A sign of NaN can be interpreted as positive or negative. - * - * @param magnitude A double value. - * @param sign A double value. - * @return A value with the magnitude of the first argument, and the sign - * of the second argument. - */ - public static double copySign(double magnitude, double sign) { - return Double.longBitsToDouble( - (Double.doubleToRawLongBits(sign) & Long.MIN_VALUE) - | (Double.doubleToRawLongBits(magnitude) & Long.MAX_VALUE)); - } - - /** - * The ULP (Unit in the Last Place) is the distance to the next value larger - * in magnitude. - * - * @param value A float value. - * @return The size of an ulp of the specified value, or Float.MIN_VALUE - * if it is +-0.0f, or +Infinity if it is +-Infinity, or NaN - * if it is NaN. - */ - public static float ulp(float value) { - if (USE_JDK_MATH) { - return Math.ulp(value); - } - /* - * Look-up table not really worth it in micro-benchmark, - * so should be worse with cache-misses. - */ - final int exponent = getExponent(value); - if (exponent >= (MIN_FLOAT_NORMAL_EXPONENT+23)) { - if (exponent == MAX_FLOAT_EXPONENT+1) { - // NaN or +-Infinity - return Math.abs(value); - } - // normal: returning 2^(exponent-23) - return Float.intBitsToFloat((exponent+(MAX_FLOAT_EXPONENT-23))<<23); - } else { - if (exponent == MIN_FLOAT_NORMAL_EXPONENT-1) { - // +-0.0f or subnormal - return Float.MIN_VALUE; - } - // subnormal result - return Float.intBitsToFloat(1<<(exponent-MIN_FLOAT_NORMAL_EXPONENT)); - } - } - - /** - * The ULP (Unit in the Last Place) is the distance to the next value larger - * in magnitude. - * - * @param value A double value. - * @return The size of an ulp of the specified value, or Double.MIN_VALUE - * if it is +-0.0, or +Infinity if it is +-Infinity, or NaN - * if it is NaN. - */ - public static double ulp(double value) { - if (USE_JDK_MATH) { - return Math.ulp(value); - } - /* - * Look-up table not really worth it in micro-benchmark, - * so should be worse with cache-misses. - */ - final int exponent = getExponent(value); - if (exponent >= (MIN_DOUBLE_NORMAL_EXPONENT+52)) { - if (exponent == MAX_DOUBLE_EXPONENT+1) { - // NaN or +-Infinity - return Math.abs(value); - } - // normal: returning 2^(exponent-52) - return Double.longBitsToDouble((exponent+(MAX_DOUBLE_EXPONENT-52L))<<52); - } else { - if (exponent == MIN_DOUBLE_NORMAL_EXPONENT-1) { - // +-0.0f or subnormal - return Double.MIN_VALUE; - } - // subnormal result - return Double.longBitsToDouble(1L<<(exponent-MIN_DOUBLE_NORMAL_EXPONENT)); - } - } - - /** - * If both arguments are +-0.0(f), (float)direction is returned. - * - * If both arguments are +Infinity or -Infinity, - * respectively +Infinity or -Infinity is returned. - * - * @param start A float value. - * @param direction A double value. - * @return The float adjacent to start towards direction, considering that - * +(-)Float.MIN_VALUE is adjacent to +(-)0.0f, and that - * +(-)Float.MAX_VALUE is adjacent to +(-)Infinity, - * or NaN if any argument is NaN. - */ - public static float nextAfter(float start, double direction) { - if (direction < start) { - // Going towards -Infinity. - if (start == 0.0f) { - // +-0.0f - return -Float.MIN_VALUE; - } - final int bits = Float.floatToRawIntBits(start); - return Float.intBitsToFloat(bits + ((bits > 0) ? -1 : 1)); - } else if (direction > start) { - // Going towards +Infinity. - // +0.0f to get rid of eventual -0.0f - final int bits = Float.floatToRawIntBits(start + 0.0f); - return Float.intBitsToFloat(bits + (bits >= 0 ? 1 : -1)); - } else if (start == direction) { - return (float)direction; - } else { - // Returning a NaN derived from the input NaN(s). - return start + (float)direction; - } - } - - /** - * If both arguments are +-0.0, direction is returned. - * - * If both arguments are +Infinity or -Infinity, - * respectively +Infinity or -Infinity is returned. - * - * @param start A double value. - * @param direction A double value. - * @return The double adjacent to start towards direction, considering that - * +(-)Double.MIN_VALUE is adjacent to +(-)0.0, and that - * +(-)Double.MAX_VALUE is adjacent to +(-)Infinity, - * or NaN if any argument is NaN. - */ - public static double nextAfter(double start, double direction) { - if (direction < start) { - // Going towards -Infinity. - if (start == 0.0) { - // +-0.0 - return -Double.MIN_VALUE; - } - final long bits = Double.doubleToRawLongBits(start); - return Double.longBitsToDouble(bits + ((bits > 0) ? -1 : 1)); - } else if (direction > start) { - // Going towards +Infinity. - // +0.0 to get rid of eventual -0.0 - final long bits = Double.doubleToRawLongBits(start + 0.0f); - return Double.longBitsToDouble(bits + (bits >= 0 ? 1 : -1)); - } else if (start == direction) { - return direction; - } else { - // Returning a NaN derived from the input NaN(s). - return start + direction; - } - } - - /** - * Semantically equivalent to nextAfter(start,Double.NEGATIVE_INFINITY). - */ - public static float nextDown(float start) { - if (start > Float.NEGATIVE_INFINITY) { - if (start == 0.0f) { - // +-0.0f - return -Float.MIN_VALUE; - } - final int bits = Float.floatToRawIntBits(start); - return Float.intBitsToFloat(bits + ((bits > 0) ? -1 : 1)); - } else if (start == Float.NEGATIVE_INFINITY) { - return Float.NEGATIVE_INFINITY; - } else { - // NaN - return start; - } - } - - /** - * Semantically equivalent to nextAfter(start,Double.NEGATIVE_INFINITY). - */ - public static double nextDown(double start) { - if (start > Double.NEGATIVE_INFINITY) { - if (start == 0.0) { - // +-0.0 - return -Double.MIN_VALUE; - } - final long bits = Double.doubleToRawLongBits(start); - return Double.longBitsToDouble(bits + ((bits > 0) ? -1 : 1)); - } else if (start == Double.NEGATIVE_INFINITY) { - return Double.NEGATIVE_INFINITY; - } else { - // NaN - return start; - } - } - - /** - * Semantically equivalent to nextAfter(start,Double.POSITIVE_INFINITY). - */ - public static float nextUp(float start) { - if (start < Float.POSITIVE_INFINITY) { - // +0.0f to get rid of eventual -0.0f - final int bits = Float.floatToRawIntBits(start + 0.0f); - return Float.intBitsToFloat(bits + (bits >= 0 ? 1 : -1)); - } else if (start == Float.POSITIVE_INFINITY) { - return Float.POSITIVE_INFINITY; - } else { - // NaN - return start; - } - } - - /** - * Semantically equivalent to nextAfter(start,Double.POSITIVE_INFINITY). - */ - public static double nextUp(double start) { - if (start < Double.POSITIVE_INFINITY) { - // +0.0 to get rid of eventual -0.0 - final long bits = Double.doubleToRawLongBits(start + 0.0); - return Double.longBitsToDouble(bits + (bits >= 0 ? 1 : -1)); - } else if (start == Double.POSITIVE_INFINITY) { - return Double.POSITIVE_INFINITY; - } else { - // NaN - return start; - } - } - - /** - * Precision may be lost if the result is subnormal. - * - * @param value A float value. - * @param scaleFactor An int value. - * @return value * 2^scaleFactor, or a value equivalent to the specified - * one if it is NaN, +-Infinity or +-0.0f. - */ - public static float scalb(float value, int scaleFactor) { - // Large enough to imply overflow or underflow for - // a finite non-zero value. - final int MAX_SCALE = 2*MAX_FLOAT_EXPONENT+23+1; - - // Making sure scaling factor is in a reasonable range. - scaleFactor = Math.max(Math.min(scaleFactor, MAX_SCALE), -MAX_SCALE); - - return (float)(((double)value) * twoPowNormal(scaleFactor)); - } - - /** - * Precision may be lost if the result is subnormal. - * - * @param value A double value. - * @param scaleFactor An int value. - * @return value * 2^scaleFactor, or a value equivalent to the specified - * one if it is NaN, +-Infinity or +-0.0. - */ - public static double scalb(double value, int scaleFactor) { - if ((scaleFactor > -MAX_DOUBLE_EXPONENT) && (scaleFactor <= MAX_DOUBLE_EXPONENT)) { - // Quick case (as done in apache FastMath). - return value * twoPowNormal(scaleFactor); - } - - // Large enough to imply overflow or underflow for - // a finite non-zero value. - final int MAX_SCALE = 2*MAX_DOUBLE_EXPONENT+52+1; - - // Making sure scaling factor is in a reasonable range. - final int exponentAdjust; - final int scaleIncrement; - final double exponentDelta; - if (scaleFactor < 0) { - scaleFactor = Math.max(scaleFactor, -MAX_SCALE); - scaleIncrement = -512; - exponentDelta = TWO_POW_N512; - } else { - scaleFactor = Math.min(scaleFactor, MAX_SCALE); - scaleIncrement = 512; - exponentDelta = TWO_POW_512; - } - - // Calculating (scaleFactor % +-512), 512 = 2^9, using - // technique from "Hacker's Delight" section 10-2. - final int t = ((scaleFactor >> (9-1)) >>> (32-9)); - exponentAdjust = ((scaleFactor + t) & (512-1)) - t; - - value *= twoPowNormal(exponentAdjust); - scaleFactor -= exponentAdjust; - - while (scaleFactor != 0) { - value *= exponentDelta; - scaleFactor -= scaleIncrement; - } - - return value; - } - - /* - * Non-redefined Math public values and treatments. - */ - - public static float abs(float a) { - return Math.abs(a); - } - - public static double abs(double a) { - return Math.abs(a); - } - - public static float min(float a, float b) { - return Math.min(a,b); - } - - public static double min(double a, double b) { - return Math.min(a,b); - } - - public static float max(float a, float b) { - return Math.max(a,b); - } - - public static double max(double a, double b) { - return Math.max(a,b); - } - - public static double IEEEremainder(double f1, double f2) { - return Math.IEEEremainder(f1,f2); - } - - public static double random() { - return Math.random(); - } - - //-------------------------------------------------------------------------- - // PRIVATE METHODS - //-------------------------------------------------------------------------- - - /** - * Non-instantiable. - */ - private FastMath() { - } - - /* - * Remainders (accurate). - */ - - /** - * @param angle Angle in radians. - * @return Remainder of (angle % (2*PI)), in [-PI,PI]. - */ - private static double remainderTwoPi(double angle) { - if (USE_JDK_MATH) { - return jdkRemainderTwoPi(angle); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - if (angle <= (4*NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2)) { - double fn = (double)(int)(angle*TWOPI_INV+0.5); - angle = (angle - fn*TWOPI_HI) - fn*TWOPI_LO; - // Ensuring range. - // HI/LO can help a bit, even though we are always far from 0. - if (angle < -Math.PI) { - angle = (angle + TWOPI_HI) + TWOPI_LO; - } else if (angle > Math.PI) { - angle = (angle - TWOPI_HI) - TWOPI_LO; - } - return negateResult ? -angle : angle; - } else if (angle < Double.POSITIVE_INFINITY) { - angle = heavyRemainderTwoPi(angle); - return negateResult ? -angle : angle; - } else { // angle is +Infinity or NaN - return Double.NaN; - } - } - - /** - * @param angle Angle in radians. - * @return Remainder of (angle % PI), in [-PI/2,PI/2]. - */ - private static double remainderPi(double angle) { - if (USE_JDK_MATH) { - return jdkRemainderPi(angle); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - if (angle <= (2*NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2)) { - double fn = (double)(int)(angle*PI_INV+0.5); - angle = (angle - fn*PI_HI) - fn*PI_LO; - // Ensuring range. - // HI/LO can help a bit, even though we are always far from 0. - if (angle < -Math.PI/2) { - angle = (angle + PI_HI) + PI_LO; - } else if (angle > Math.PI/2) { - angle = (angle - PI_HI) - PI_LO; - } - return negateResult ? -angle : angle; - } else if (angle < Double.POSITIVE_INFINITY) { - angle = heavyRemainderPi(angle); - return negateResult ? -angle : angle; - } else { // angle is +Infinity or NaN - return Double.NaN; - } - } - - /** - * @param angle Angle in radians. - * @return Bits of double corresponding to remainder of (angle % (PI/2)), - * in [-PI/4,PI/4], with quadrant encoded in exponent bits. - */ - private static long remainderPiO2(double angle) { - if (USE_JDK_MATH) { - return jdkRemainderPiO2(angle, false); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - if (angle <= NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2) { - int n = (int)(angle*PIO2_INV+0.5); - double fn = (double)n; - angle = (angle - fn*PIO2_HI) - fn*PIO2_LO; - // Ensuring range. - // HI/LO can help a bit, even though we are always far from 0. - if (angle < -Math.PI/4) { - angle = (angle + PIO2_HI) + PIO2_LO; - n--; - } else if (angle > Math.PI/4) { - angle = (angle - PIO2_HI) - PIO2_LO; - n++; - } - if (negateResult) { - angle = -angle; - } - return encodeRemainderAndQuadrant(angle, n&3); - } else if (angle < Double.POSITIVE_INFINITY) { - return heavyRemainderPiO2(angle, negateResult); - } else { // angle is +Infinity or NaN - return encodeRemainderAndQuadrant(Double.NaN, 0); - } - } - - /* - * Remainders (fast). - */ - - /** - * Not accurate for large values. - * - * @param angle Angle in radians. - * @return Remainder of (angle % (2*PI)), in [-PI,PI]. - */ - private static double remainderTwoPiFast(double angle) { - if (USE_JDK_MATH) { - return jdkRemainderTwoPi(angle); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - // - We don't bother with values higher than (2*PI*(2^52)), - // since they are spaced by 2*PI or more from each other. - // - For large values, we don't use % because it might be very slow, - // and we split computation in two, because cast from double to int - // with large numbers might be very slow also. - if (angle <= TWO_POW_26*(2*Math.PI)) { - // ok - } else if (angle <= TWO_POW_52*(2*Math.PI)) { - // Computing remainder of angle modulo TWO_POW_26*(2*PI). - double fn = (double)(int)(angle*(TWOPI_INV/TWO_POW_26)+0.5); - angle = (angle - fn*(TWOPI_HI*TWO_POW_26)) - fn*(TWOPI_LO*TWO_POW_26); - // Here, angle is in [-TWO_POW_26*PI,TWO_POW_26*PI], or so. - if (angle < 0.0) { - angle = -angle; - negateResult = !negateResult; - } - } else if (angle < Double.POSITIVE_INFINITY) { - return 0.0; - } else { // angle is +Infinity or NaN - return Double.NaN; - } - - // Computing remainder of angle modulo 2*PI. - double fn = (double)(int)(angle*TWOPI_INV+0.5); - angle = (angle - fn*TWOPI_HI) - fn*TWOPI_LO; - - // Ensuring range. - // HI/LO can help a bit, even though we are always far from 0. - if (angle < -Math.PI) { - angle = (angle + TWOPI_HI) + TWOPI_LO; - } else if (angle > Math.PI) { - angle = (angle - TWOPI_HI) - TWOPI_LO; - } - return negateResult ? -angle : angle; - } - - /** - * Not accurate for large values. - * - * @param angle Angle in radians. - * @return Remainder of (angle % PI), in [-PI/2,PI/2]. - */ - private static double remainderPiFast(double angle) { - if (USE_JDK_MATH) { - return jdkRemainderPi(angle); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - // - We don't bother with values higher than (PI*(2^52)), - // since they are spaced by PI or more from each other. - // - For large values, we don't use % because it might be very slow, - // and we split computation in two, because cast from double to int - // with large numbers might be very slow also. - if (angle <= TWO_POW_26*Math.PI) { - // ok - } else if (angle <= TWO_POW_52*Math.PI) { - // Computing remainder of angle modulo TWO_POW_26*PI. - double fn = (double)(int)(angle*(PI_INV/TWO_POW_26)+0.5); - angle = (angle - fn*(PI_HI*TWO_POW_26)) - fn*(PI_LO*TWO_POW_26); - // Here, angle is in [-TWO_POW_26*PI/2,TWO_POW_26*PI/2], or so. - if (angle < 0.0) { - angle = -angle; - negateResult = !negateResult; - } - } else if (angle < Double.POSITIVE_INFINITY) { - return 0.0; - } else { // angle is +Infinity or NaN - return Double.NaN; - } - - // Computing remainder of angle modulo PI. - double fn = (double)(int)(angle*PI_INV+0.5); - angle = (angle - fn*PI_HI) - fn*PI_LO; - - // Ensuring range. - // HI/LO can help a bit, even though we are always far from 0. - if (angle < -Math.PI/2) { - angle = (angle + PI_HI) + PI_LO; - } else if (angle > Math.PI/2) { - angle = (angle - PI_HI) - PI_LO; - } - return negateResult ? -angle : angle; - } -} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/IntWrapper.java b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/IntWrapper.java deleted file mode 100644 index 812e5a22d..000000000 --- a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/IntWrapper.java +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ -package space.kscience.kmath.jafama; - -public class IntWrapper { - public int value; - @Override - public String toString() { - return Integer.toString(this.value); - } -} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt index 2b6cc3a5a..2557004e9 100644 --- a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt @@ -1,6 +1,7 @@ package space.kscience.kmath.jafama import space.kscience.kmath.operations.* +import net.jafama.* /** * Advanced Number-like semifield that implements basic operations. @@ -55,7 +56,7 @@ public interface ExtendedField : ExtendedFieldOperations, Field, Numeri * A field for [Double] without boxing. Does not produce appropriate field element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public object DoubleField : ExtendedField, Norm, ScaleOperations { +public object JafamaDoubleField : ExtendedField, Norm, ScaleOperations { public override inline val zero: Double get() = 0.0 public override inline val one: Double get() = 1.0 diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/NumbersUtils.java b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/NumbersUtils.java deleted file mode 100644 index 6fdd9dea5..000000000 --- a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/NumbersUtils.java +++ /dev/null @@ -1,2647 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ -package space.kscience.kmath.jafama; - -/** - * Class containing various basic utility methods to deal with numbers. - * This class is meant to be light (no big look-up tables or such). - * - * Check methods return boolean if success, - * for it allows to use them in assertions. - * - * toString methods use capital letters, unlike JDK's toStrings, for it is more - * readable (especially, "l" and "1" can easily be confused with one another). - * - * Some methods have an int version additionally to the long version, - * even though long version could be used instead, for performance reasons, - * either for the methods themselves (if they do computations with ints - * instead of longs), or to be used in an int use case (like methods - * checking whether or not a signed int can fit in such number of bits). - */ -public final class NumbersUtils { - - //-------------------------------------------------------------------------- - // MEMBERS - //-------------------------------------------------------------------------- - - /** - * Double.MIN_NORMAL since Java 6. - */ - public static final double DOUBLE_MIN_NORMAL = Double.longBitsToDouble(0x0010000000000000L); // 2.2250738585072014E-308 - - /** - * Float.MIN_NORMAL since Java 6. - */ - public static final float FLOAT_MIN_NORMAL = Float.intBitsToFloat(0x00800000); // 1.17549435E-38f - - private static final int MIN_DOUBLE_EXPONENT = -1074; - private static final int MAX_DOUBLE_EXPONENT = 1023; - - /** - * All possible upper case chars for representing a number as a String. - */ - private final static char[] CHAR_BY_DIGIT; - static { - final char minDecimal = '0'; - final char maxDecimal = '9'; - final int n1 = maxDecimal - minDecimal + 1; - final char minLetter = 'A'; - final char maxLetter = 'Z'; - final int n2 = maxLetter - minLetter + 1; - CHAR_BY_DIGIT = new char[n1+n2]; - int i=0; - for (char c=minDecimal;c<=maxDecimal;c++) { - CHAR_BY_DIGIT[i++] = c; - } - for (char c=minLetter;c<=maxLetter;c++) { - CHAR_BY_DIGIT[i++] = c; - } - } - - /** - * For power-of-two radixes only. - */ - private static final int[] DIV_SHIFT_BY_RADIX; - static { - DIV_SHIFT_BY_RADIX = new int[32+1]; - int shift=1; - for (int radix=2;radix<=32;radix*=2) { - DIV_SHIFT_BY_RADIX[radix] = shift++; - } - } - - private final static int[] MAX_NBR_OF_NEG_INT_DIGITS_BY_RADIX = new int[Character.MAX_RADIX+1]; - private final static int[] MAX_NBR_OF_NEG_LONG_DIGITS_BY_RADIX = new int[Character.MAX_RADIX+1]; - static { - for (int radix=Character.MIN_RADIX;radix<=Character.MAX_RADIX;radix++) { - /* - * Brutal but works. - * -1 for the sign. - */ - MAX_NBR_OF_NEG_INT_DIGITS_BY_RADIX[radix] = Integer.toString(Integer.MIN_VALUE, radix).length()-1; - MAX_NBR_OF_NEG_LONG_DIGITS_BY_RADIX[radix] = Long.toString(Long.MIN_VALUE, radix).length()-1; - } - } - - static final double NO_CSN_MIN_BOUND_INCL = 1e-3; - static final double NO_CSN_MAX_BOUND_EXCL = 1e7; - - private static final double PIO2_HI = Double.longBitsToDouble(0x3FF921FB54400000L); // 1.57079632673412561417e+00 first 33 bits of pi/2 - private static final double PIO2_LO = Double.longBitsToDouble(0x3DD0B4611A626331L); // 6.07710050650619224932e-11 pi/2 - PIO2_HI - private static final double PI_HI = 2*PIO2_HI; - private static final double PI_LO = 2*PIO2_LO; - private static final double TWOPI_HI = 4*PIO2_HI; - private static final double TWOPI_LO = 4*PIO2_LO; - - //-------------------------------------------------------------------------- - // PUBLIC METHODS - //-------------------------------------------------------------------------- - - /** - * @return True if the specified values are equal or both NaN, false otherwise. - */ - public static boolean equal(float a, float b) { - // Only does one test if a == b. - return (a == b) ? true : ((a != a) && (b != b)); - } - - /** - * @return True if the specified values are equal or both NaN, false otherwise. - */ - public static boolean equal(double a, double b) { - // Only does one test if a == b. - return (a == b) ? true : ((a != a) && (b != b)); - } - - /** - * @return True if the specified value is a mathematical integer, - * false otherwise (which includes NaN and +-Infinity). - */ - public static boolean isMathematicalInteger(float value) { - // Doing magnitude test first, for cast - // might be very slow for huge values. - // It also helps be faster for huge values, - // for which the test with cast always fail. - value = Math.abs(value); - return ((value >= (float)(1<<23) - && (value != Float.POSITIVE_INFINITY))) - || (value == (float)(int)value); - } - - /** - * @return True if the specified value is a mathematical integer, - * false otherwise (which includes NaN and +-Infinity). - */ - public static boolean isMathematicalInteger(double value) { - // Doing magnitude test first, for cast - // might be very slow for huge values. - // It also helps be faster for huge values, - // for which the test with cast always fail. - value = Math.abs(value); - return ((value >= (double)(1L<<52)) - && (value != Double.POSITIVE_INFINITY)) - || (value == (double)(long)value); - } - - /** - * @param value A float value. - * @return True if the specified value is equidistant from two adjacent - * mathematical integers, false otherwise (which includes NaN - * and +-Infinity). - */ - public static boolean isEquidistant(float value) { - if (false) { - // Also works, but slower. - final int bits = Float.floatToRawIntBits(value); - final int exponent = ((bits>>23)&0xFF)-127; - final int nbrOfPostCommaBits = 23 - exponent; - if ((nbrOfPostCommaBits <= 0) || (nbrOfPostCommaBits >= 25)) { - // No mantissa bit after comma, or all mantissa bits - // (including implicit 1) are at least one bit away from it. - //System.out.println("can't be"); - return false; - } - final int mantissa = 0x00800000|(bits&0x007FFFFF); - final int postCommaMask = ~((-1)<>52))&0x7FF)-1023; - final int nbrOfPostCommaBits = 52 - exponent; - if ((nbrOfPostCommaBits <= 0) || (nbrOfPostCommaBits >= 54)) { - // No mantissa bit after comma, or all mantissa bits - // (including implicit 1) are at least one bit away from it. - return false; - } - final long mantissa = 0x0010000000000000L|(bits&0x000FFFFFFFFFFFFFL); - final long postCommaMask = ~((-1L)< value is NaN or +-Infinity - return !(value-value == 0.0f); - } - - /** - * @param value A double value. - * @return True if the specified value is NaN or +-Infinity, false otherwise. - */ - public static boolean isNaNOrInfinite(double value) { - // value-value is not equal to 0.0 (and is NaN) <-> value is NaN or +-Infinity - return !(value-value == 0.0); - } - - /** - * @param value A float value. - * @return -1 if sign bit is 1, 1 if sign bit is 0. - */ - public static int signFromBit(float value) { - return ((Float.floatToRawIntBits(value)>>30)|1); - } - - /** - * @param value A double value. - * @return -1 if sign bit is 1, 1 if sign bit is 0. - */ - public static long signFromBit(double value) { - // Returning a long, to avoid useless cast into int. - return ((Double.doubleToRawLongBits(value)>>62)|1); - } - - /* - * min/max ranges - */ - - /** - * @return True if the specified value is in the specified range (inclusive), false otherwise. - */ - public static boolean isInRange(int min, int max, int a) { - return (min <= a) && (a <= max); - } - - /** - * @return True if the specified value is in the specified range (inclusive), false otherwise. - */ - public static boolean isInRange(long min, long max, long a) { - return (min <= a) && (a <= max); - } - - /** - * Returns false if any value is NaN. - * - * @return True if the specified value is in the specified range (inclusive), false otherwise. - */ - public static boolean isInRange(float min, float max, float a) { - return (min <= a) && (a <= max); - } - - /** - * Returns false if any value is NaN. - * - * @return True if the specified value is in the specified range (inclusive), false otherwise. - */ - public static boolean isInRange(double min, double max, double a) { - return (min <= a) && (a <= max); - } - - /* - * - */ - - /** - * @return True if does not throw. - * @throws IllegalArgumentException if the specified value is not in the specified range (inclusive). - */ - public static boolean checkIsInRange(int min, int max, int a) { - if (!isInRange(min, max, a)) { - throw new IllegalArgumentException(a+" not in ["+min+","+max+"]"); - } - return true; - } - - /** - * @return True if does not throw. - * @throws IllegalArgumentException if the specified value is not in the specified range (inclusive). - */ - public static boolean checkIsInRange(long min, long max, long a) { - if (!isInRange(min, max, a)) { - throw new IllegalArgumentException(a+" not in ["+min+","+max+"]"); - } - return true; - } - - /** - * @return True if does not throw. - * @throws IllegalArgumentException if the specified value is not in the specified range (inclusive) - * or any parameter is NaN. - */ - public static boolean checkIsInRange(float min, float max, float a) { - if (!isInRange(min, max, a)) { - throw new IllegalArgumentException(a+" not in ["+min+","+max+"]"); - } - return true; - } - - /** - * @return True if does not throw. - * @throws IllegalArgumentException if the specified value is not in the specified range (inclusive) - * or any parameter is NaN. - */ - public static boolean checkIsInRange(double min, double max, double a) { - if (!isInRange(min, max, a)) { - throw new IllegalArgumentException(a+" not in ["+min+","+max+"]"); - } - return true; - } - - /* - * - */ - - /** - * @param min A value. - * @param max A value. - * @param a A value. - * @return min if a <= min, else max if a >= max, else a. - */ - public static int toRange(int min, int max, int a) { - if (a <= min) { - return min; - } else if (a >= max) { - return max; - } else { - return a; - } - } - - /** - * @param min A value. - * @param max A value. - * @param a A value. - * @return min if a <= min, else max if a >= max, else a. - */ - public static long toRange(long min, long max, long a) { - if (a <= min) { - return min; - } else if (a >= max) { - return max; - } else { - return a; - } - } - - /** - * @param min A value. - * @param max A value. - * @param a A value. - * @return min if a <= min, else max if a >= max, else a. - */ - public static float toRange(float min, float max, float a) { - if (a <= min) { - return min; - } else if (a >= max) { - return max; - } else { - return a; - } - } - - /** - * @param min A value. - * @param max A value. - * @param a A value. - * @return min if a <= min, else max if a >= max, else a. - */ - public static double toRange(double min, double max, double a) { - if (a <= min) { - return min; - } else if (a >= max) { - return max; - } else { - return a; - } - } - - /* - * bitwise ranges - */ - - /** - * @param bitSize A number of bits, in [1,32]. - * @return True if the specified value fits as a signed integer - * over the specified number of bits, false otherwise. - * @throws IllegalArgumentException if the specified number of bits is not in [1,32]. - */ - public static boolean isInRangeSigned(int a, int bitSize) { - checkBitSizeForSignedInt(bitSize); - return (minSignedIntForBitSize_noCheck(bitSize) <= a) && (a <= maxSignedIntForBitSize_noCheck(bitSize)); - } - - /** - * @param bitSize A number of bits, in [1,64]. - * @return True if the specified value fits as a signed integer - * over the specified number of bits, false otherwise. - * @throws IllegalArgumentException if the specified number of bits is not in [1,64]. - */ - public static boolean isInRangeSigned(long a, int bitSize) { - checkBitSizeForSignedLong(bitSize); - return (minSignedLongForBitSize_noCheck(bitSize) <= a) && (a <= maxSignedLongForBitSize_noCheck(bitSize)); - } - - /** - * @param bitSize A number of bits, in [1,31]. - * @return True if the specified value fits as an unsigned integer - * over the specified number of bits, false otherwise. - * @throws IllegalArgumentException if the specified number of bits is not in [1,31]. - */ - public static boolean isInRangeUnsigned(int a, int bitSize) { - return isInRange(0, maxUnsignedIntForBitSize(bitSize), a); - } - - /** - * @param bitSize A number of bits, in [1,63]. - * @return True if the specified value fits as an unsigned integer - * over the specified number of bits, false otherwise. - * @throws IllegalArgumentException if the specified number of bits is not in [1,63]. - */ - public static boolean isInRangeUnsigned(long a, int bitSize) { - return isInRange(0, maxUnsignedLongForBitSize(bitSize), a); - } - - /* - * - */ - - /** - * @param bitSize A number of bits, in [1,32]. - * @return True if does not throw. - * @throws IllegalArgumentException if the specified value does not fit - * as a signed integer over the specified number of bits. - */ - public static boolean checkIsInRangeSigned(int a, int bitSize) { - if (!isInRangeSigned(a, bitSize)) { - throw new IllegalArgumentException(a+" does not fit as a signed value over "+bitSize+" bits"); - } - return true; - } - - /** - * @param bitSize A number of bits, in [1,64]. - * @return True if does not throw. - * @throws IllegalArgumentException if the specified value does not fit - * as a signed integer over the specified number of bits. - */ - public static boolean checkIsInRangeSigned(long a, int bitSize) { - if (!isInRangeSigned(a, bitSize)) { - throw new IllegalArgumentException(a+" does not fit as a signed value over "+bitSize+" bits"); - } - return true; - } - - /** - * @param bitSize A number of bits, in [1,31]. - * @return True if does not throw. - * @throws IllegalArgumentException if the specified value does not fit - * as an unsigned integer over the specified number of bits. - */ - public static boolean checkIsInRangeUnsigned(int a, int bitSize) { - if (!isInRangeUnsigned(a, bitSize)) { - throw new IllegalArgumentException(a+" does not fit as an unsigned value over "+bitSize+" bits"); - } - return true; - } - - /** - * @param bitSize A number of bits, in [1,63]. - * @return True if does not throw. - * @throws IllegalArgumentException if the specified value does not fit - * as an unsigned integer over the specified number of bits. - */ - public static boolean checkIsInRangeUnsigned(long a, int bitSize) { - if (!isInRangeUnsigned(a, bitSize)) { - throw new IllegalArgumentException(a+" does not fit as an unsigned value over "+bitSize+" bits"); - } - return true; - } - - /* - * masks (int) - */ - - /** - * @param bitSize A number of bits, in [0,32]. - * @return Mask with the specified number of left bits set with 0, - * and other bits set with 1. - */ - public static int intMaskMSBits0(int bitSize) { - checkIsInRange(0, 32, bitSize); - // Shifting in two times, for >>> doesn't work for full bit size (<< as well). - final int halfish = (bitSize>>1); - return ((-1)>>>halfish)>>>(bitSize-halfish); - } - - /** - * @param bitSize A number of bits, in [0,32]. - * @return Mask with the specified number of left bits set with 1, - * and other bits set with 0. - */ - public static int intMaskMSBits1(int bitSize) { - return ~intMaskMSBits0(bitSize); - } - - /** - * @param bitSize A number of bits, in [0,32]. - * @return Mask with the specified number of right bits set with 0, - * and other bits set with 1. - */ - public static int intMaskLSBits0(int bitSize) { - return ~intMaskMSBits0(32-bitSize); - } - - /** - * @param bitSize A number of bits, in [0,32]. - * @return Mask with the specified number of right bits set with 1, - * and other bits set with 0. - */ - public static int intMaskLSBits1(int bitSize) { - return intMaskMSBits0(32-bitSize); - } - - /* - * masks (long) - */ - - /** - * @param bitSize A number of bits, in [0,64]. - * @return Mask with the specified number of left bits set with 0, - * and other bits set with 1. - */ - public static long longMaskMSBits0(int bitSize) { - checkIsInRange(0, 64, bitSize); - // Shifting in two times, for >>> doesn't work for full bit size (<< as well). - final int halfish = (bitSize>>1); - return ((-1L)>>>halfish)>>>(bitSize-halfish); - } - - /** - * @param bitSize A number of bits, in [0,64]. - * @return Mask with the specified number of left bits set with 1, - * and other bits set with 0. - */ - public static long longMaskMSBits1(int bitSize) { - return ~longMaskMSBits0(bitSize); - } - - /** - * @param bitSize A number of bits, in [0,64]. - * @return Mask with the specified number of right bits set with 0, - * and other bits set with 1. - */ - public static long longMaskLSBits0(int bitSize) { - return ~longMaskMSBits0(64-bitSize); - } - - /** - * @param bitSize A number of bits, in [0,64]. - * @return Mask with the specified number of right bits set with 1, - * and other bits set with 0. - */ - public static long longMaskLSBits1(int bitSize) { - return longMaskMSBits0(64-bitSize); - } - - /* - * signed/unsigned - */ - - /** - * @return Unsigned value corresponding to bits of the specified byte. - */ - public static short byteAsUnsigned(byte value) { - return (short)(((short)value) & 0xFF); - } - - /** - * @return Unsigned value corresponding to bits of the specified short. - */ - public static int shortAsUnsigned(short value) { - return ((int)value) & 0xFFFF; - } - - /** - * @return Unsigned value corresponding to bits of the specified int. - */ - public static long intAsUnsigned(int value) { - return ((long)value) & 0xFFFFFFFF; - } - - /* - * bitwise ranges - */ - - /** - * @return True if a signed int value can be read over the specified number of bits, - * i.e. if it is in [1,32], false otherwise. - */ - public static boolean isValidBitSizeForSignedInt(int bitSize) { - return (bitSize > 0) && (bitSize <= 32); - } - - /** - * @return True if a signed long value can be read over the specified number of bits, - * i.e. if it is in [1,64], false otherwise. - */ - public static boolean isValidBitSizeForSignedLong(int bitSize) { - return (bitSize > 0) && (bitSize <= 64); - } - - /** - * @return True if an unsigned int value can be read over the specified number of bits, - * i.e. if it is in [1,31], false otherwise. - */ - public static boolean isValidBitSizeForUnsignedInt(int bitSize) { - return (bitSize > 0) && (bitSize < 32); - } - - /** - * @return True if an unsigned long value can be read over the specified number of bits, - * i.e. if it is in [1,63], false otherwise. - */ - public static boolean isValidBitSizeForUnsignedLong(int bitSize) { - return (bitSize > 0) && (bitSize < 64); - } - - /* - * - */ - - /** - * @return True if does not throw. - * @throws IllegalArgumentException if a signed int value can't be read over the - * specified number of bits, i.e. if it is not in [1,32]. - */ - public static boolean checkBitSizeForSignedInt(int bitSize) { - if (!isValidBitSizeForSignedInt(bitSize)) { - throw new IllegalArgumentException("bit size ["+bitSize+"] must be in [1,32] for signed int values"); - } - return true; - } - - /** - * @return True if does not throw. - * @throws IllegalArgumentException if a signed long value can't be read over the - * specified number of bits, i.e. if it is not in [1,64]. - */ - public static boolean checkBitSizeForSignedLong(int bitSize) { - if (!isValidBitSizeForSignedLong(bitSize)) { - throw new IllegalArgumentException("bit size ["+bitSize+"] must be in [1,64] for signed long values"); - } - return true; - } - - /** - * @return True if does not throw. - * @throws IllegalArgumentException if an unsigned int value can't be read over the - * specified number of bits, i.e. if it is not in [1,31]. - */ - public static boolean checkBitSizeForUnsignedInt(int bitSize) { - if (!isValidBitSizeForUnsignedInt(bitSize)) { - throw new IllegalArgumentException("bit size ["+bitSize+"] must be in [1,31] for unsigned int values"); - } - return true; - } - - /** - * @return True if does not throw. - * @throws IllegalArgumentException if an unsigned long value can't be read over the - * specified number of bits, i.e. if it is not in [1,63]. - */ - public static boolean checkBitSizeForUnsignedLong(int bitSize) { - if (!isValidBitSizeForUnsignedLong(bitSize)) { - throw new IllegalArgumentException("bit size ["+bitSize+"] must be in [1,63] for unsigned long values"); - } - return true; - } - - /* - * - */ - - /** - * @param bitSize A number of bits in [1,32]. - * @return The min signed int value that can be stored over the specified number of bits. - * @throws IllegalArgumentException if the specified number of bits is out of range. - */ - public static int minSignedIntForBitSize(int bitSize) { - checkBitSizeForSignedInt(bitSize); - return minSignedIntForBitSize_noCheck(bitSize); - } - - /** - * @param bitSize A number of bits in [1,64]. - * @return The min signed long value that can be stored over the specified number of bits. - * @throws IllegalArgumentException if the specified number of bits is out of range. - */ - public static long minSignedLongForBitSize(int bitSize) { - checkBitSizeForSignedLong(bitSize); - return minSignedLongForBitSize_noCheck(bitSize); - } - - /** - * @param bitSize A number of bits in [1,32]. - * @return The max signed int value that can be stored over the specified number of bits. - * @throws IllegalArgumentException if the specified number of bits is out of range. - */ - public static int maxSignedIntForBitSize(int bitSize) { - checkBitSizeForSignedInt(bitSize); - return maxSignedIntForBitSize_noCheck(bitSize); - } - - /** - * @param bitSize A number of bits in [1,64]. - * @return The max signed long value that can be stored over the specified number of bits. - * @throws IllegalArgumentException if the specified number of bits is out of range. - */ - public static long maxSignedLongForBitSize(int bitSize) { - checkBitSizeForSignedLong(bitSize); - return maxSignedLongForBitSize_noCheck(bitSize); - } - - /** - * @param bitSize A number of bits in [1,31]. - * @return The max unsigned int value that can be stored over the specified number of bits. - * @throws IllegalArgumentException if the specified number of bits is out of range. - */ - public static int maxUnsignedIntForBitSize(int bitSize) { - checkBitSizeForUnsignedInt(bitSize); - // i.e. (1<>(31-bitSize)); - } - - /** - * @param bitSize A number of bits in [1,63]. - * @return The max unsigned long value that can be stored over the specified number of bits. - * @throws IllegalArgumentException if the specified number of bits is out of range. - */ - public static long maxUnsignedLongForBitSize(int bitSize) { - checkBitSizeForUnsignedLong(bitSize); - // i.e. (1L<>(63-bitSize)); - } - - /* - * - */ - - /** - * @return The number of bits required to store the specified value as a signed integer, - * i.e. a result in [1,32]. - */ - public static int bitSizeForSignedValue(int value) { - if (value > 0) { - return 33-Integer.numberOfLeadingZeros(value); - } else if (value == 0) { - return 1; - } else { - // Works for Integer.MIN_VALUE as well. - return 33-Integer.numberOfLeadingZeros(-value-1); - } - } - - /** - * @return The number of bits required to store the specified value as a signed integer, - * i.e. a result in [1,64]. - */ - public static int bitSizeForSignedValue(long value) { - if (value > 0) { - return 65-Long.numberOfLeadingZeros(value); - } else if (value == 0) { - return 1; - } else { - // Works for Long.MIN_VALUE as well. - return 65-Long.numberOfLeadingZeros(-value-1); - } - } - - /** - * @param value An integer value in [0,Integer.MAX_VALUE]. - * @return The number of bits required to store the specified value as an unsigned integer, - * i.e. a result in [1,31]. - * @throws IllegalArgumentException if the specified value is < 0. - */ - public static int bitSizeForUnsignedValue(int value) { - if (value > 0) { - return 32-Integer.numberOfLeadingZeros(value); - } else { - if (value == 0) { - return 1; - } else { - throw new IllegalArgumentException("unsigned value ["+value+"] must be >= 0"); - } - } - } - - /** - * @param value An integer value in [0,Long.MAX_VALUE]. - * @return The number of bits required to store the specified value as an unsigned integer, - * i.e. a result in [1,63]. - * @throws IllegalArgumentException if the specified value is < 0. - */ - public static int bitSizeForUnsignedValue(long value) { - if (value > 0) { - return 64-Long.numberOfLeadingZeros(value); - } else { - if (value == 0) { - return 1; - } else { - throw new IllegalArgumentException("unsigned value ["+value+"] must be >= 0"); - } - } - } - - /* - * integer functions - */ - - /** - * @return 1 if the specified value is > 0, 0 if it is 0, -1 otherwise. - */ - public static int signum(int a) { - return (a < 0) ? -1 : ((a == 0) ? 0 : 1); - } - - /** - * @return 1 if the specified value is > 0, 0 if it is 0, -1 otherwise. - */ - public static int signum(long a) { - return (a < 0) ? -1 : ((a == 0) ? 0 : 1); - } - - /** - * @return True if the specified value is even, false otherwise. - */ - public static boolean isEven(int a) { - return ((a&1) == 0); - } - - /** - * @return True if the specified value is even, false otherwise. - */ - public static boolean isEven(long a) { - // faster to work on ints - return isEven((int)a); - } - - /** - * @return True if the specified value is odd, false otherwise. - */ - public static boolean isOdd(int a) { - return ((a&1) != 0); - } - - /** - * @return True if the specified value is odd, false otherwise. - */ - public static boolean isOdd(long a) { - // faster to work on ints - return isOdd((int)a); - } - - /** - * @return True if the specified values are both even or both odd, false otherwise. - */ - public static boolean haveSameEvenness(int a, int b) { - return (((a^b)&1) == 0); - } - - /** - * @return True if the specified values are both even or both odd, false otherwise. - */ - public static boolean haveSameEvenness(long a, long b) { - // faster to work on ints - return haveSameEvenness((int)a, (int)b); - } - - /** - * @return True if the specified values are both >= 0 or both < 0, false otherwise. - */ - public static boolean haveSameSign(int a, int b) { - return ((a^b) >= 0); - } - - /** - * @return True if the specified values are both >= 0 or both < 0, false otherwise. - */ - public static boolean haveSameSign(long a, long b) { - return ((a^b) >= 0); - } - - /** - * @return True if the specified value is a power of two, - * i.e. a value of the form 2^k, with k >= 0. - */ - public static boolean isPowerOfTwo(int a) { - if (a <= 0) { - return false; - } - if (false) { - // also works - return (a & -a) == a; - } - return (a & (a-1)) == 0; - } - - /** - * @return True if the specified value is a power of two, - * i.e. a value of the form 2^k, with k >= 0. - */ - public static boolean isPowerOfTwo(long a) { - if (a <= 0) { - return false; - } - if (false) { - // also works - return (a & -a) == a; - } - return (a & (a-1)) == 0; - } - - /** - * @return True if the specified value is a signed power of two, - * i.e. a value of the form +-2^k, with k >= 0. - */ - public static boolean isSignedPowerOfTwo(int a) { - if (a > 0) { - return (a & (a-1)) == 0; - } else { - if (a == -a) { - // a is 0 or Integer.MIN_VALUE - return (a != 0); - } - return ((-a) & (-a-1)) == 0; - } - } - - /** - * @return True if the specified value is a signed power of two, - * i.e. a value of the form +-2^k, with k >= 0. - */ - public static boolean isSignedPowerOfTwo(long a) { - if (a > 0) { - return (a & (a-1)) == 0; - } else { - if (a == -a) { - // a is 0 or Long.MIN_VALUE - return (a != 0); - } - return ((-a) & (-a-1)) == 0; - } - } - - /** - * @param a A value in [1,Integer.MAX_VALUE]. - * @return The highest power of two <= a. - */ - public static int floorPowerOfTwo(int a) { - if (a <= 0) { - throw new IllegalArgumentException("a ["+a+"] must be > 0"); - } - return Integer.highestOneBit(a); - } - - /** - * @param a A value in [1,Long.MAX_VALUE]. - * @return The highest power of two <= a. - */ - public static long floorPowerOfTwo(long a) { - if (a <= 0) { - throw new IllegalArgumentException("a ["+a+"] must be > 0"); - } - // Faster than copying int method - // (less computations on long). - return 1L << (63 - Long.numberOfLeadingZeros(a)); - } - - /** - * @param a A value in [0,2^30]. - * @return The lowest power of two >= a. - */ - public static int ceilingPowerOfTwo(int a) { - checkIsInRange(0, (1<<30), a); - return (a >= 2) ? Integer.highestOneBit((a-1)<<1) : 1; - } - - /** - * @param a A value in [0,2^62]. - * @return The lowest power of two >= a. - */ - public static long ceilingPowerOfTwo(long a) { - checkIsInRange(0L, (1L<<62), a); - // Faster than copying int method - // (less computations on long). - return 1L << (64 - Long.numberOfLeadingZeros(a - 1)); - } - - /** - * @return Mean without overflow, rounded to the lowest value (i.e. mathematical floor((a+b)/2), using floating point division). - */ - public static int meanLow(int a, int b) { - return (a & b) + ((a ^ b) >> 1); - } - - /** - * @return Mean without overflow, rounded to the lowest value (i.e. mathematical floor((a+b)/2), using floating point division). - */ - public static long meanLow(long a, long b) { - return (a & b) + ((a ^ b) >> 1); - } - - /** - * @return Mean without overflow, rounded to the value of smallest magnitude (i.e. mathematical (a+b)/2, using integer division). - */ - public static int meanSml(int a, int b) { - int result = meanLow(a,b); - if (!haveSameEvenness(a, b)) { - // inexact - if (((a&b) < 0) || (((a|b) < 0) && (a+b < 0))) { - // both < 0, or only one is < 0 and it has the largest magnitude - result++; - } - } - return result; - } - - /** - * @return Mean without overflow, rounded to the value of smallest magnitude (i.e. mathematical (a+b)/2, using integer division). - */ - public static long meanSml(long a, long b) { - long result = meanLow(a,b); - if (!haveSameEvenness(a, b)) { - // inexact - if (((a&b) < 0) || (((a|b) < 0) && (a+b < 0))) { - // both < 0, or only one is < 0 and it has the largest magnitude - result++; - } - } - return result; - } - - /** - * Useful because a positive int value could not represent half the width - * of full int range width, which is mathematically Integer.MAX_VALUE+1. - * - * @return Minus half the range width (inclusive, and rounded to the value of smaller magnitude) - * between the specified bounds. - * @throws IllegalArgumentException if min > max. - */ - public static int negHalfWidth(int min, int max) { - if (min > max) { - throw new IllegalArgumentException("min ["+min+"] must be <= max ["+max+"]"); - } - int mean = meanLow(min, max); - return min - mean - ((min^max)&1); - } - - /** - * Useful because a positive long value could not represent half the width - * of full long range width, which is mathematically Long.MAX_VALUE+1. - * - * @return Minus half the range width (inclusive, and rounded to the value of smaller magnitude) - * between the specified bounds. - * @throws IllegalArgumentException if min > max. - */ - public static long negHalfWidth(long min, long max) { - if (min > max) { - throw new IllegalArgumentException("min ["+min+"] must be <= max ["+max+"]"); - } - long mean = meanLow(min, max); - return min - mean - ((min^max)&1); - } - - /** - * This treatment being designed for optimization, the fact that spot - * is a signed power of two is not checked. - * - * @param value A value. - * @param spot A signed power of two (i.e. a value of the form +-2^k, k >= 0). - * @return value % spot, i.e. a value in ]-|spot|,|spot|[. - */ - public static int moduloSignedPowerOfTwo(int value, int spot) { - if (spot == Integer.MIN_VALUE) { - return (value != Integer.MIN_VALUE) ? value : 0; - } else { - int s = (value>>31); - return ((((value+s) ^ s) & (abs(spot)-1)) + s) ^ s; - } - } - - /** - * This treatment being designed for optimization, the fact that spot - * is a signed power of two is not checked. - * - * @param value A value. - * @param spot A signed power of two (i.e. a value of the form +-2^k, k >= 0). - * @return value % spot, i.e. a value in ]-|spot|,|spot|[. - */ - public static long moduloSignedPowerOfTwo(long value, long spot) { - if (spot == Long.MIN_VALUE) { - return (value != Long.MIN_VALUE) ? value : 0; - } else { - long s = (value>>63); - return ((((value+s) ^ s) & (abs(spot)-1)) + s) ^ s; - } - } - - /** - * @param value An integer value > 0. - * @return The integer part of the logarithm, in base 2, of the specified value, - * i.e. a result in [0,30] - * @throws IllegalArgumentException if the specified value is <= 0. - */ - public static int log2(int value) { - if (value <= 0) { - throw new IllegalArgumentException("value ["+value+"] must be > 0"); - } - return 31-Integer.numberOfLeadingZeros(value); - } - - /** - * @param value An integer value > 0. - * @return The integer part of the logarithm, in base 2, of the specified value, - * i.e. a result in [0,62] - * @throws IllegalArgumentException if the specified value is <= 0. - */ - public static int log2(long value) { - if (value <= 0) { - throw new IllegalArgumentException("value ["+value+"] must be > 0"); - } - return 63-Long.numberOfLeadingZeros(value); - } - - /** - * Possibly faster than java.lang.Math.abs(int). - * - * @return The absolute value, except if value is Integer.MIN_VALUE, for which it returns Integer.MIN_VALUE. - */ - public static int abs(int a) { - return (a^(a>>31))-(a>>31); - } - - /** - * Possibly faster than java.lang.Math.abs(long). - * - * @return The absolute value, except if value is Long.MIN_VALUE, for which it returns Long.MIN_VALUE. - */ - public static long abs(long a) { - return (a^(a>>63))-(a>>63); - } - - /** - * @return The negative of the absolute value (always exact). - */ - public static int absNeg(int a) { - return (a>>31)-(a^(a>>31)); - } - - /** - * @return The negative of the absolute value (always exact). - */ - public static long absNeg(long a) { - return (a>>63)-(a^(a>>63)); - } - - /** - * If the specified value is in int range, the returned value is identical. - * - * @return An int hash of the specified value. - */ - public static int intHash(long a) { - if (false) { - // also works - int hash = ((int)(a>>32)) ^ ((int)a); - if (a < 0) { - hash = -hash-1; - } - return hash; - } - int hash = ((int)(a>>32)) + ((int)a); - if (a < 0) { - hash++; - } - return hash; - } - - /** - * @param a An int value. - * @return The specified value as byte. - * @throws ArithmeticException if the specified value is not in [Byte.MIN_VALUE,Byte.MAX_VALUE] range. - */ - public static byte asByte(int a) { - if (a != (byte)a) { - throw new ArithmeticException("overflow: "+a); - } - return (byte)a; - } - - /** - * @param a A long value. - * @return The specified value as int. - * @throws ArithmeticException if the specified value is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. - */ - public static int asInt(long a) { - if (a != (int)a) { - throw new ArithmeticException("overflow: "+a); - } - return (int)a; - } - - /** - * @param a A long value. - * @return The closest int value in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. - */ - public static int toInt(long a) { - if (a != (int)a) { - return (a < 0) ? Integer.MIN_VALUE : Integer.MAX_VALUE; - } - return (int)a; - } - - /** - * @param a An int value. - * @param b An int value. - * @return The mathematical result of a+b. - * @throws ArithmeticException if the mathematical result of a+b is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. - */ - public static int plusExact(int a, int b) { - final int sum = a + b; - // HD 2-12 Overflow iff both arguments - // have the opposite sign of the result. - if (((a ^ sum) & (b ^ sum)) < 0) { - throw new ArithmeticException("overflow: "+a+"+"+b); - } - return sum; - } - - /** - * @param a A long value. - * @param b A long value. - * @return The mathematical result of a+b. - * @throws ArithmeticException if the mathematical result of a+b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. - */ - public static long plusExact(long a, long b) { - final long sum = a + b; - // HD 2-12 Overflow iff both arguments - // have the opposite sign of the result. - if (((a ^ sum) & (b ^ sum)) < 0) { - throw new ArithmeticException("overflow: "+a+"+"+b); - } - return sum; - } - - /** - * @param a An int value. - * @param b An int value. - * @return The int value of [Integer.MIN_VALUE,Integer.MAX_VALUE] range which is the closest to mathematical result of a+b. - */ - public static int plusBounded(int a, int b) { - return toInt(((long)a) + ((long)b)); - } - - /** - * @param a A long value. - * @param b A long value. - * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a+b. - */ - public static long plusBounded(long a, long b) { - final long sum = a + b; - if (((a ^ sum) & (b ^ sum)) < 0) { - return (sum >= 0) ? Long.MIN_VALUE : Long.MAX_VALUE; - } - return sum; - } - - /** - * @param a An int value. - * @param b An int value. - * @return The mathematical result of a-b. - * @throws ArithmeticException if the mathematical result of a-b is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. - */ - public static int minusExact(int a, int b) { - final int diff = a - b; - // HD 2-12 Overflow iff the arguments have different signs and - // the sign of the result is different than the sign of "a". - if (((a ^ b) & (a ^ diff)) < 0) { - throw new ArithmeticException("integer overflow"); - } - return diff; - } - - /** - * @param a A long value. - * @param b A long value. - * @return The mathematical result of a-b. - * @throws ArithmeticException if the mathematical result of a-b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. - */ - public static long minusExact(long a, long b) { - final long diff = a - b; - // HD 2-12 Overflow iff the arguments have different signs and - // the sign of the result is different than the sign of "a". - if (((a ^ b) & (a ^ diff)) < 0) { - throw new ArithmeticException("integer overflow"); - } - return diff; - } - - /** - * @param a An int value. - * @param b An int value. - * @return The int value of [Integer.MIN_VALUE,Integer.MAX_VALUE] range which is the closest to mathematical result of a-b. - */ - public static int minusBounded(int a, int b) { - return toInt(((long)a) - ((long)b)); - } - - /** - * @param a A long value. - * @param b A long value. - * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a-b. - */ - public static long minusBounded(long a, long b) { - final long diff = a - b; - if (((a ^ b) & (a ^ diff)) < 0) { - return (diff >= 0) ? Long.MIN_VALUE : Long.MAX_VALUE; - } - return diff; - } - - /** - * @param a An int value. - * @param b An int value. - * @return The mathematical result of a*b. - * @throws ArithmeticException if the mathematical result of a*b is not in [Integer.MIN_VALUE,Integer.MAX_VALUE] range. - */ - public static int timesExact(int a, int b) { - final long prod = a * (long)b; - if (prod != (int)prod) { - throw new ArithmeticException("overflow: "+a+"*"+b); - } - return (int)prod; - } - - /** - * @param a A long value. - * @param b A long value. - * @return The mathematical result of a*b. - * @throws ArithmeticException if the mathematical result of a*b is not in [Long.MIN_VALUE,Long.MAX_VALUE] range. - */ - public static long timesExact(long a, long b) { - final long prod = a * b; - final long absA = abs(a); - final long absB = abs(b); - if (((absA|absB)>>>31) != 0) { - // Some bits greater than 2^31 that might cause overflow - // Check the result using the divide operator - // and check for the special case of Long.MIN_VALUE * -1 - if (((b != 0) && (prod/b != a)) || - ((a == Long.MIN_VALUE) && (b == -1))) { - throw new ArithmeticException("overflow: "+a+"*"+b); - } - } - return prod; - } - - /** - * @param a An int value. - * @param b An int value. - * @return The int value of [Integer.MIN_VALUE,Integer.MAX_VALUE] range which is the closest to mathematical result of a*b. - */ - public static int timesBounded(int a, int b) { - return (int)(a * (double)b); - } - - /** - * @param a A long value. - * @param b A long value. - * @return The long value of [Long.MIN_VALUE,Long.MAX_VALUE] range which is the closest to mathematical result of a*b. - */ - public static long timesBounded(long a, long b) { - final long prod = a * b; - final long absA = abs(a); - final long absB = abs(b); - if (((absA|absB)>>>31) != 0) { - // Some bits greater than 2^31 that might cause overflow - // Check the result using the divide operator - // and check for the special case of Long.MIN_VALUE * -1 - if (((b != 0) && (prod/b != a)) || - ((a == Long.MIN_VALUE) && (b == -1))) { - return ((a^b) >= 0) ? Long.MAX_VALUE : Long.MIN_VALUE; - } - } - return prod; - } - - /* - * powers - */ - - /** - * Returns the exact result, provided it's in double range, - * i.e. if power is in [-1074,1023]. - * - * @param power An int power. - * @return 2^power as a double, or +-Infinity in case of overflow. - */ - public static double twoPow(int power) { - if (power <= -MAX_DOUBLE_EXPONENT) { // Not normal. - if (power >= MIN_DOUBLE_EXPONENT) { // Subnormal. - return Double.longBitsToDouble(0x0008000000000000L>>(-(power+MAX_DOUBLE_EXPONENT))); - } else { // Underflow. - return 0.0; - } - } else if (power > MAX_DOUBLE_EXPONENT) { // Overflow. - return Double.POSITIVE_INFINITY; - } else { // Normal. - return Double.longBitsToDouble(((long)(power+MAX_DOUBLE_EXPONENT))<<52); - } - } - - /** - * @param power An int power. - * @return 2^power as an int. - * @throws ArithmeticException if the mathematical result - * is not in int range, i.e. if power is not in [0,30]. - */ - public static int twoPowAsIntExact(int power) { - if ((power < 0) || (power > 30)) { - throw new ArithmeticException("integer overflow"); - } - return 1 << power; - } - - /** - * @param power An int power. - * @return 2^power as an int, or the closest power of two in int range - * in case of overflow, i.e. if power is not in [0,30]. - */ - public static int twoPowAsIntBounded(int power) { - power = toRange(0, 30, power); - return 1 << power; - } - - /** - * @param power An int power. - * @return 2^power as a long. - * @throws ArithmeticException if the mathematical result - * is not in long range, i.e. if power is not in [0,62]. - */ - public static long twoPowAsLongExact(int power) { - if ((power < 0) || (power > 62)) { - throw new ArithmeticException("long overflow"); - } - return 1L << power; - } - - /** - * @param power An int power. - * @return 2^power as a long, or the closest power of two in long range - * in case of overflow, i.e. if power is not in [0,62]. - */ - public static long twoPowAsLongBounded(int power) { - power = toRange(0, 62, power); - return 1L << power; - } - - /** - * @param a A value. - * @return a*a. - */ - public static int pow2(int a) { - return a*a; - } - - /** - * @param a A value. - * @return a*a. - */ - public static long pow2(long a) { - return a*a; - } - - /** - * @param a A value. - * @return a*a. - */ - public static float pow2(float a) { - return a*a; - } - - /** - * Strict version. - * - * @param a A value. - * @return a*a. - */ - public static strictfp float pow2_strict(float a) { - return a*a; - } - - /** - * @param a A value. - * @return a*a. - */ - public static double pow2(double a) { - return a*a; - } - - /** - * Strict version. - * - * @param a A value. - * @return a*a. - */ - public static strictfp double pow2_strict(double a) { - return a*a; - } - - /** - * @param a A value. - * @return a*a*a. - */ - public static int pow3(int a) { - return a*a*a; - } - - /** - * @param a A value. - * @return a*a*a. - */ - public static long pow3(long a) { - return a*a*a; - } - - /** - * @param a A value. - * @return a*a*a. - */ - public static float pow3(float a) { - return a*a*a; - } - - /** - * Strict version. - * - * @param a A value. - * @return a*a*a. - */ - public static strictfp float pow3_strict(float a) { - return a*a*a; - } - - /** - * @param a A value. - * @return a*a*a. - */ - public static double pow3(double a) { - return a*a*a; - } - - /** - * Strict version. - * - * @param a A value. - * @return a*a*a. - */ - public static strictfp double pow3_strict(double a) { - return a*a*a; - } - - /* - * Accurate +-m*PI/n. - */ - - /** - * @param angRad An angle, in radians. - * @return angRad + 2*PI, accurately computed. - */ - public static double plus2PI(double angRad) { - if (angRad > -Math.PI) { - // LO then HI, for better accuracy (if starting near 0). - return (angRad + TWOPI_LO) + TWOPI_HI; - } else { - // HI then LO, for better accuracy (if ending near 0). - return (angRad + TWOPI_HI) + TWOPI_LO; - } - } - - /** - * Strict version. - * - * @param angRad An angle, in radians. - * @return angRad + 2*PI, accurately computed. - */ - public static strictfp double plus2PI_strict(double angRad) { - if (angRad > -Math.PI) { - // LO then HI, for better accuracy (if starting near 0). - return (angRad + TWOPI_LO) + TWOPI_HI; - } else { - // HI then LO, for better accuracy (if ending near 0). - return (angRad + TWOPI_HI) + TWOPI_LO; - } - } - - /** - * @param angRad An angle, in radians. - * @return angRad - 2*PI, accurately computed. - */ - public static double minus2PI(double angRad) { - if (angRad < Math.PI) { - // LO then HI, for better accuracy (if starting near 0). - return (angRad - TWOPI_LO) - TWOPI_HI; - } else { - // HI then LO, for better accuracy (if ending near 0). - return (angRad - TWOPI_HI) - TWOPI_LO; - } - } - - /** - * Strict version. - * - * @param angRad An angle, in radians. - * @return angRad - 2*PI, accurately computed. - */ - public static strictfp double minus2PI_strict(double angRad) { - if (angRad < Math.PI) { - // LO then HI, for better accuracy (if starting near 0). - return (angRad - TWOPI_LO) - TWOPI_HI; - } else { - // HI then LO, for better accuracy (if ending near 0). - return (angRad - TWOPI_HI) - TWOPI_LO; - } - } - - /** - * @param angRad An angle, in radians. - * @return angRad + PI, accurately computed. - */ - public static double plusPI(double angRad) { - if (angRad > -Math.PI/2) { - // LO then HI, for better accuracy (if starting near 0). - return (angRad + PI_LO) + PI_HI; - } else { - // HI then LO, for better accuracy (if ending near 0). - return (angRad + PI_HI) + PI_LO; - } - } - - /** - * Strict version. - * - * @param angRad An angle, in radians. - * @return angRad + PI, accurately computed. - */ - public static strictfp double plusPI_strict(double angRad) { - if (angRad > -Math.PI/2) { - // LO then HI, for better accuracy (if starting near 0). - return (angRad + PI_LO) + PI_HI; - } else { - // HI then LO, for better accuracy (if ending near 0). - return (angRad + PI_HI) + PI_LO; - } - } - - /** - * @param angRad An angle, in radians. - * @return angRad - PI, accurately computed. - */ - public static double minusPI(double angRad) { - if (angRad < Math.PI/2) { - // LO then HI, for better accuracy (if starting near 0). - return (angRad - PI_LO) - PI_HI; - } else { - // HI then LO, for better accuracy (if ending near 0). - return (angRad - PI_HI) - PI_LO; - } - } - - /** - * Strict version. - * - * @param angRad An angle, in radians. - * @return angRad - PI, accurately computed. - */ - public static strictfp double minusPI_strict(double angRad) { - if (angRad < Math.PI/2) { - // LO then HI, for better accuracy (if starting near 0). - return (angRad - PI_LO) - PI_HI; - } else { - // HI then LO, for better accuracy (if ending near 0). - return (angRad - PI_HI) - PI_LO; - } - } - - /** - * @param angRad An angle, in radians. - * @return angRad + PI/2, accurately computed. - */ - public static double plusPIO2(double angRad) { - if (angRad > -Math.PI/4) { - // LO then HI, for better accuracy (if starting near 0). - return (angRad + PIO2_LO) + PIO2_HI; - } else { - // HI then LO, for better accuracy (if ending near 0). - return (angRad + PIO2_HI) + PIO2_LO; - } - } - - /** - * Strict version. - * - * @param angRad An angle, in radians. - * @return angRad + PI/2, accurately computed. - */ - public static strictfp double plusPIO2_strict(double angRad) { - if (angRad > -Math.PI/4) { - // LO then HI, for better accuracy (if starting near 0). - return (angRad + PIO2_LO) + PIO2_HI; - } else { - // HI then LO, for better accuracy (if ending near 0). - return (angRad + PIO2_HI) + PIO2_LO; - } - } - - /** - * @param angRad An angle, in radians. - * @return angRad - PI/2, accurately computed. - */ - public static double minusPIO2(double angRad) { - if (angRad < Math.PI/4) { - // LO then HI, for better accuracy (if starting near 0). - return (angRad - PIO2_LO) - PIO2_HI; - } else { - // HI then LO, for better accuracy (if ending near 0). - return (angRad - PIO2_HI) - PIO2_LO; - } - } - - /** - * Strict version. - * - * @param angRad An angle, in radians. - * @return angRad - PI/2, accurately computed. - */ - public static strictfp double minusPIO2_strict(double angRad) { - if (angRad < Math.PI/4) { - // LO then HI, for better accuracy (if starting near 0). - return (angRad - PIO2_LO) - PIO2_HI; - } else { - // HI then LO, for better accuracy (if ending near 0). - return (angRad - PIO2_HI) - PIO2_LO; - } - } - - /* - * toString (radix) - */ - - /** - * @param radix Radix to be checked. - * @return True if does not throw. - * @throws IllegalArgumentException if the specified radix is not in [2,36]. - */ - public static boolean checkRadix(int radix) { - if (!isInRange(Character.MIN_RADIX, Character.MAX_RADIX, radix)) { - throw new IllegalArgumentException("radix ["+radix+"] must be in ["+Character.MIN_RADIX+","+Character.MAX_RADIX+"]"); - } - return true; - } - - /** - * @param radix A radix in [2,36]. - * @return Number of characters (minus sign included) - * to represent the specified value in the specified radix. - */ - public static int computeNbrOfChars(int value, int radix) { - if (value < 0) { - // 1 for sign - return 1 + computeNbrOfDigits_negValue(value, radix); - } else { - return computeNbrOfDigits_negValue(-value, radix); - } - } - - /** - * @param radix A radix in [2,36]. - * @return Number of characters (minus sign included) - * to represent the specified value in the specified radix. - */ - public static int computeNbrOfChars(long value, int radix) { - if (value < 0) { - // 1 for sign - return 1 + computeNbrOfDigits_negValue(value, radix); - } else { - return computeNbrOfDigits_negValue(-value, radix); - } - } - - /** - * @param radix A radix in [2,36]. - * @param paddingUpTo Number of digits (sign excluded) up to which left-padding with zeros is done. - * @return Number of characters (minus sign included) - * to represent the specified value in the specified radix. - */ - public static int computeNbrOfChars(int value, int radix, int paddingUpTo) { - if (value < 0) { - // 1 for sign - return 1 + Math.max(paddingUpTo, computeNbrOfDigits_negValue(value, radix)); - } else { - return Math.max(paddingUpTo, computeNbrOfDigits_negValue(-value, radix)); - } - } - - /** - * @param radix A radix in [2,36]. - * @param paddingUpTo Number of digits (sign excluded) up to which left-padding with zeros is done. - * @return Number of characters (minus sign included) - * to represent the specified value in the specified radix. - */ - public static int computeNbrOfChars(long value, int radix, int paddingUpTo) { - if (value < 0) { - // 1 for sign - return 1 + Math.max(paddingUpTo, computeNbrOfDigits_negValue(value, radix)); - } else { - return Math.max(paddingUpTo, computeNbrOfDigits_negValue(-value, radix)); - } - } - - /** - * @param radix A radix in [2,36]. - * @return Number of digits of the specified value in the specified radix. - */ - public static int computeNbrOfDigits(int value, int radix) { - return computeNbrOfDigits_negValue(-abs(value), radix); - } - - /** - * @param radix A radix in [2,36]. - * @return Number of digits of the specified value in the specified radix. - */ - public static int computeNbrOfDigits(long value, int radix) { - return computeNbrOfDigits_negValue(-abs(value), radix); - } - - /** - * @param radix A radix in [2,36]. - * @param paddingUpTo Number of digits (sign excluded) up to which left-padding with zeros is done. - * @return Number of digits of the specified value in the specified radix, - * including the specified padding. - */ - public static int computeNbrOfDigits(int value, int radix, int paddingUpTo) { - return Math.max(paddingUpTo,computeNbrOfDigits(value, radix)); - } - - /** - * @param radix A radix in [2,36]. - * @param paddingUpTo Number of digits (sign excluded) up to which left-padding with zeros is done. - * @return Number of digits of the specified value in the specified radix, - * including the specified padding. - */ - public static int computeNbrOfDigits(long value, int radix, int paddingUpTo) { - return Math.max(paddingUpTo,computeNbrOfDigits(value, radix)); - } - - /** - * This method just delegates to Integer.toString(int), - * but is defined here to complete the API. - * - * @return String representation of the specified value in base 10. - */ - public static String toString(int value) { - return Integer.toString(value); - } - - /** - * This method just delegates to Long.toString(long), - * but is defined here to complete the API. - * - * @return String representation of the specified value in base 10. - */ - public static String toString(long value) { - return Long.toString(value); - } - - /** - * @param radix A radix in [2,36]. - * @return String representation of the specified value in the specified radix. - * @throws IllegalArgumentException if the specified radix is out of range. - */ - public static String toString(int value, int radix) { - return toString(value, radix, 0); - } - - /** - * @param radix A radix in [2,36]. - * @return String representation of the specified value in the specified radix. - * @throws IllegalArgumentException if the specified radix is out of range. - */ - public static String toString(long value, int radix) { - return toString(value, radix, 0); - } - - /** - * @param radix A radix in [2,36]. - * @param paddingUpTo Number of digits (sign excluded) up to which left-padding with zeros is done. - * @return String representation of the specified value in the specified radix. - * @throws IllegalArgumentException if the specified radix is out of range. - */ - public static String toString(int value, int radix, int paddingUpTo) { - // Only one test if radix+paddingUpTo != 10. - if ((radix+paddingUpTo == 10) && (paddingUpTo == 0)) { - // Using JDK's optimized algorithm. - return Integer.toString(value); - } - - int negValue; - final int signSize; - final boolean negative = (value < 0); - if (negative) { - negValue = value; - signSize = 1; - } else { - negValue = -value; - signSize = 0; - } - // Faster if we just use max possible number of characters (33), - // but we prefer to take care of garbage's memory footprint. - // Checks radix. - final int nbrOfChars = signSize + Math.max(paddingUpTo, computeNbrOfDigits_negValue(negValue, radix)); - - final char[] chars = new char[nbrOfChars]; - - int charPos = nbrOfChars; - - final boolean radixIsPowerOfTwo = ((radix & (radix-1)) == 0); - // Not allowing Integer.MIN_VALUE so it can be negated. - if (radixIsPowerOfTwo && (negValue != Integer.MIN_VALUE)) { - final int mask = radix-1; - final int divShift = DIV_SHIFT_BY_RADIX[radix]; - while (negValue <= -radix) { - chars[--charPos] = CHAR_BY_DIGIT[(int)((-negValue) & mask)]; - negValue = -((-negValue) >> divShift); - } - } else { - while (negValue <= -radix) { - chars[--charPos] = CHAR_BY_DIGIT[(int)(-(negValue % radix))]; - negValue /= radix; - } - } - chars[--charPos] = CHAR_BY_DIGIT[(int)(-negValue)]; - - while (charPos > signSize) { - chars[--charPos] = '0'; - } - - if (negative) { - chars[0] = '-'; - } - - return new String(chars); - } - - /** - * @param radix A radix in [2,36]. - * @param paddingUpTo Number of digits (sign excluded) up to which left-padding with zeros is done. - * @return String representation of the specified value in the specified radix. - * @throws IllegalArgumentException if the specified radix is out of range. - */ - public static String toString(long value, int radix, int paddingUpTo) { - // Only one test if radix+paddingUpTo != 10. - if ((radix+paddingUpTo == 10) && (paddingUpTo == 0)) { - // Using JDK's optimized algorithm. - return Long.toString(value); - } - - long negValue; - final int signSize; - final boolean negative = (value < 0); - if (negative) { - negValue = value; - signSize = 1; - } else { - negValue = -value; - signSize = 0; - } - // Checks radix. - final int nbrOfChars = signSize + Math.max(paddingUpTo, computeNbrOfDigits_negValue(negValue, radix)); - - final char[] chars = new char[nbrOfChars]; - - int charPos = nbrOfChars; - - final boolean radixIsPowerOfTwo = ((radix & (radix-1)) == 0); - // Not allowing Long.MIN_VALUE so it can be negated. - if (radixIsPowerOfTwo && (negValue != Long.MIN_VALUE)) { - final int mask = radix-1; - final int divShift = DIV_SHIFT_BY_RADIX[radix]; - while (negValue <= -radix) { - chars[--charPos] = CHAR_BY_DIGIT[(int)((-negValue) & mask)]; - negValue = -((-negValue) >> divShift); - } - } else { - while (negValue <= -radix) { - chars[--charPos] = CHAR_BY_DIGIT[(int)(-(negValue % radix))]; - negValue /= radix; - } - } - chars[--charPos] = CHAR_BY_DIGIT[(int)(-negValue)]; - - while (charPos > signSize) { - chars[--charPos] = '0'; - } - - if (negative) { - chars[0] = '-'; - } - - return new String(chars); - } - - /* - * toString (bits) - */ - - /** - * @param firstBitPos First bit position (inclusive). - * @param lastBitPosExcl Last bit position (exclusive). - * @return True if does not throw. - * @throws IllegalArgumentException if the specified bit range does not fit in a byte. - */ - public static boolean checkBitPositionsByte(int firstBitPos, int lastBitPosExcl) { - return checkBitPositions(firstBitPos, lastBitPosExcl, 8); - } - - /** - * @param firstBitPos First bit position (inclusive). - * @param lastBitPosExcl Last bit position (exclusive). - * @return True if does not throw. - * @throws IllegalArgumentException if the specified bit range does not fit in a short. - */ - public static boolean checkBitPositionsShort(int firstBitPos, int lastBitPosExcl) { - return checkBitPositions(firstBitPos, lastBitPosExcl, 16); - } - - /** - * @param firstBitPos First bit position (inclusive). - * @param lastBitPosExcl Last bit position (exclusive). - * @return True if does not throw. - * @throws IllegalArgumentException if the specified bit range does not fit in an int. - */ - public static boolean checkBitPositionsInt(int firstBitPos, int lastBitPosExcl) { - return checkBitPositions(firstBitPos, lastBitPosExcl, 32); - } - - /** - * @param firstBitPos First bit position (inclusive). - * @param lastBitPosExcl Last bit position (exclusive). - * @return True if does not throw. - * @throws IllegalArgumentException if the specified bit range does not fit in a long. - */ - public static boolean checkBitPositionsLong(int firstBitPos, int lastBitPosExcl) { - return checkBitPositions(firstBitPos, lastBitPosExcl, 64); - } - - /** - * @return String representation of specified bits, in big endian. - */ - public static String toStringBits(byte bits) { - final char[] chars = new char[8]; - int bitIndex = 8; - while (--bitIndex >= 0) { - chars[7-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); - } - return new String(chars); - } - - /** - * @return String representation of specified bits, in big endian. - */ - public static String toStringBits(short bits) { - final char[] chars = new char[16]; - int bitIndex = 16; - while (--bitIndex >= 0) { - chars[15-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); - } - return new String(chars); - } - - /** - * @return String representation of specified bits, in big endian. - */ - public static String toStringBits(int bits) { - final char[] chars = new char[32]; - int bitIndex = 32; - while (--bitIndex >= 0) { - chars[31-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); - } - return new String(chars); - } - - /** - * @return String representation of specified bits, in big endian. - */ - public static String toStringBits(long bits) { - final char[] chars = new char[64]; - int bitIndex = 64; - while (--bitIndex >= 0) { - chars[63-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); - } - return new String(chars); - } - - /** - * @param firstBitPos First bit position (inclusive). - * @param lastBitPosExcl Last bit position (exclusive). - * @param bigEndian True for bits to be added in big endian order (MSBit to LSBit) - * false for little endian order. - * @param padding True if underscores must be added instead of out-of-range bits, - * false to just add characters corresponding to in-range bits. - * @return String representation of specified bits. - */ - public static String toStringBits( - byte bits, - int firstBitPos, - int lastBitPosExcl, - boolean bigEndian, - boolean padding) { - checkBitPositionsByte(firstBitPos, lastBitPosExcl); - return toStringBits_0_32_bitPosAlreadyChecked(8,bits, firstBitPos, lastBitPosExcl, bigEndian, padding); - } - - /** - * @param firstBitPos First bit position (inclusive). - * @param lastBitPosExcl Last bit position (exclusive). - * @param bigEndian True for bits to be added in big endian order (MSBit to LSBit) - * false for little endian order. - * @param padding True if underscores must be added instead of out-of-range bits, - * false to just add characters corresponding to in-range bits. - * @return String representation of specified bits. - */ - public static String toStringBits( - short bits, - int firstBitPos, - int lastBitPosExcl, - boolean bigEndian, - boolean padding) { - checkBitPositionsShort(firstBitPos, lastBitPosExcl); - return toStringBits_0_32_bitPosAlreadyChecked(16,bits, firstBitPos, lastBitPosExcl, bigEndian, padding); - } - - /** - * @param firstBitPos First bit position (inclusive). - * @param lastBitPosExcl Last bit position (exclusive). - * @param bigEndian True for bits to be added in big endian order (MSBit to LSBit) - * false for little endian order. - * @param padding True if underscores must be added instead of out-of-range bits, - * false to just add characters corresponding to in-range bits. - * @return String representation of specified bits. - */ - public static String toStringBits( - int bits, - int firstBitPos, - int lastBitPosExcl, - boolean bigEndian, - boolean padding) { - checkBitPositionsInt(firstBitPos, lastBitPosExcl); - return toStringBits_0_32_bitPosAlreadyChecked(32,bits, firstBitPos, lastBitPosExcl, bigEndian, padding); - } - - /** - * @param firstBitPos First bit position (inclusive). - * @param lastBitPosExcl Last bit position (exclusive). - * @param bigEndian True for bits to be added in big endian order (MSBit to LSBit) - * false for little endian order. - * @param padding True if underscores must be added instead of out-of-range bits, - * false to just add characters corresponding to in-range bits. - * @return String representation of specified bits. - */ - public static String toStringBits( - long bits, - int firstBitPos, - int lastBitPosExcl, - boolean bigEndian, - boolean padding) { - checkBitPositionsLong(firstBitPos, lastBitPosExcl); - final int bitSize = 64; - final int bitSizeM1 = bitSize-1; - final int lastBitPos = lastBitPosExcl-1; - if (padding) { - final int nbrOfChars = bitSize; - final char[] chars = new char[nbrOfChars]; - int bitIndex = bitSizeM1; - if (bigEndian) { - final int firstBitIndex = bitSizeM1-lastBitPos; - final int lastBitIndex = bitSizeM1-firstBitPos; - while (bitIndex > lastBitIndex) { - chars[bitSizeM1-bitIndex] = '_'; - --bitIndex; - } - while (bitIndex >= firstBitIndex) { - chars[bitSizeM1-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); - --bitIndex; - } - while (bitIndex >= 0) { - chars[bitSizeM1-bitIndex] = '_'; - --bitIndex; - } - } else { - while (bitIndex > lastBitPos) { - chars[bitIndex] = '_'; - --bitIndex; - } - while (bitIndex >= firstBitPos) { - chars[bitIndex] = (char)('0'+((bits>>bitIndex)&1)); - --bitIndex; - } - while (bitIndex >= 0) { - chars[bitIndex] = '_'; - --bitIndex; - } - } - return new String(chars); - } else { - final int nbrOfChars = (lastBitPosExcl - firstBitPos); - final char[] chars = new char[nbrOfChars]; - if (bigEndian) { - final int firstBitIndex = bitSizeM1-lastBitPos; - final int lastBitIndex = bitSizeM1-firstBitPos; - int bitIndex = lastBitIndex; - while (bitIndex >= firstBitIndex) { - chars[lastBitIndex-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); - --bitIndex; - } - } else { - int bitIndex = lastBitPos; - while (bitIndex >= firstBitPos) { - chars[bitIndex-firstBitPos] = (char)('0'+((bits>>bitIndex)&1)); - --bitIndex; - } - } - return new String(chars); - } - } - - /* - * toString (floating points) - * - * toStringCSN(double) and toStringNoCSN(double) - * could be made faster, by using directly internals - * of Double.toString(double), but this would require - * copy-paste of much tricky code from JDK, and - * the overhead of our little rework is relatively - * negligible. - */ - - /** - * @param value A double value. - * @return String representing the specified value, - * using "computerized scientific notation", - * which Double.toString(double) uses for non-infinite - * values, when |value| < 1e-3 or |value| >= 1e7. - */ - public static String toStringCSN(double value) { - // Quick case (also to get rid of +-0.0, - // for which Double.toString(double) doesn't use CSN). - if (value == 0.0) { - if (Double.doubleToRawLongBits(value) < 0) { - return "-0.0E0"; - } else { - return "0.0E0"; - } - } - - final double abs = Math.abs(value); - if ((abs >= NO_CSN_MIN_BOUND_INCL) && (abs < NO_CSN_MAX_BOUND_EXCL)) { - final boolean neg = (value < 0.0); - - final String rawAbs = Double.toString(abs); - if (abs >= 1.0) { - /* - * 0123456 - * 12.3456 ===> 1.23456E1 - * 123.0 ===> 1.23E2 - */ - final int dotIndex = rawAbs.indexOf((int)'.'); - final int powerOfTen = dotIndex-1; - final StringBuilder sb = new StringBuilder(); - if (neg) { - sb.append('-'); - } - // Adding unit-or-above digits, with dot after first one. - sb.append(rawAbs.charAt(0)); - sb.append('.'); - sb.append(rawAbs,1,dotIndex); - if ((value != (int)value) || (abs < 10.0)) { - // Adding below-unit digits (possibly just 0 if abs < 10.0, - // to end up for example with "3.0E0" instead of "3.E0"). - sb.append(rawAbs,dotIndex+1,rawAbs.length()); - } - sb.append('E'); - sb.append(CHAR_BY_DIGIT[powerOfTen]); - return sb.toString(); - } else { - /* - * 012345678 - * 0.0123456 ===> 1.23456E-2 - * 0.01 ===> 1.0E-2 - */ - int nonZeroIndex = 1; - while (rawAbs.charAt(++nonZeroIndex) == '0') { - } - // Negative. - final int powerOfTen = 1-nonZeroIndex; - final int nbrOfSignificantDigitsPastDot = (rawAbs.length() - (nonZeroIndex+1)); - final StringBuilder sb = new StringBuilder(); - if (neg) { - sb.append('-'); - } - sb.append(rawAbs.charAt(nonZeroIndex)); - sb.append('.'); - if (nbrOfSignificantDigitsPastDot > 0) { - // If bug 4428022 make rawAbs being something like "0.0010", - // we add the last '0' here after the dot, which is fine. - sb.append(rawAbs,nonZeroIndex+1,rawAbs.length()); - } else { - sb.append('0'); - } - sb.append("E-"); - sb.append(CHAR_BY_DIGIT[-powerOfTen]); - return sb.toString(); - } - } else { - return Double.toString(value); - } - } - - /** - * @param value A double value. - * @return String representing the specified value, - * not in "computerized scientific notation", - * which Double.toString(double) uses for non-infinite - * values, when |value| < 1e-3 or |value| >= 1e7. - */ - public static String toStringNoCSN(double value) { - // Quick case. - // Should also work with long instead of int, - // but less obvious (due to roundings...), - // and we just want to speed up the more common - // case of "small" integer values. - final int intValue = (int)value; - if (value == intValue) { - if (value == 0.0) { - if (Double.doubleToRawLongBits(value) < 0) { - return "-0.0"; - } else { - return "0.0"; - } - } else { - return Integer.toString(intValue)+".0"; - } - } - - final String raw = Double.toString(value); - final double abs = Math.abs(value); - if (abs >= NO_CSN_MAX_BOUND_EXCL) { - if (abs == Double.POSITIVE_INFINITY) { - return raw; - } - /* - * 0123456789 - * 1.234567E5 ===> 123456.7 - * 1.23456E5 ===> 123456.0 (adding 0) - * 1.23E5 ===> 123000.0 - * 1.0E5 ===> 100000.0 - */ - // "." close to start, so using indexOf. - final int dotIndex = raw.indexOf((int)'.'); - // "E" close to end, so using lastIndexOf. - final int eIndex = raw.lastIndexOf((int)'E'); - final int powerOfTen = Integer.parseInt(raw.substring(eIndex+1)); - final int nbrOfSignificantLoDigits = (eIndex - dotIndex - 1); - final int nbrOfZerosToAddBeforeDot = (powerOfTen - nbrOfSignificantLoDigits); - - int start; - int end; - - final StringBuilder sb = new StringBuilder(); - sb.append(raw,0,dotIndex); - if (nbrOfZerosToAddBeforeDot >= 0) { - // Can copy all digits that were between '.' and 'E'. - sb.append(raw,dotIndex+1,eIndex); - for (int i=0;i 0.0001234 - * 1.0E-4 ===> 0.0001 - */ - // "." close to start, so using indexOf. - final int dotIndex = raw.indexOf((int)'.'); - // "E" close to end, so using lastIndexOf. - final int eIndex = raw.lastIndexOf((int)'E'); - // Negative. - final int powerOfTen = Integer.parseInt(raw.substring(eIndex+1)); - final int nbrOfZerosToAddAfterDot = (-powerOfTen-1); - - final StringBuilder sb = new StringBuilder(); - if (value < 0.0) { - sb.append("-0."); - } else { - sb.append("0."); - } - for (int i=0;i>(32-bitSize)); - } - - private static long minSignedLongForBitSize_noCheck(int bitSize) { - // i.e. (-1L<<(bitSize-1)) - return (Long.MIN_VALUE>>(64-bitSize)); - } - - private static int maxSignedIntForBitSize_noCheck(int bitSize) { - // i.e. (1<<(bitSize-1))-1 - return (Integer.MAX_VALUE>>(32-bitSize)); - } - - private static long maxSignedLongForBitSize_noCheck(int bitSize) { - // i.e. (1L<<(bitSize-1))-1 - return (Long.MAX_VALUE>>(64-bitSize)); - } - - /* - * - */ - - /** - * @throws IllegalArgumentException if the specified radix is out of range. - */ - private static int computeNbrOfDigits_negValue(int negValue, int radix) { - checkRadix(radix); - final int maxNbrOfDigits = MAX_NBR_OF_NEG_INT_DIGITS_BY_RADIX[radix]; - int p = radix; - for (int i=1;i -p) { - return i; - } - p *= radix; - } - return maxNbrOfDigits; - } - - /** - * @throws IllegalArgumentException if the specified radix is out of range. - */ - private static int computeNbrOfDigits_negValue(long negValue, int radix) { - checkRadix(radix); - final int maxNbrOfDigits = MAX_NBR_OF_NEG_LONG_DIGITS_BY_RADIX[radix]; - long p = radix; - for (int i=1;i -p) { - return i; - } - p *= radix; - } - return maxNbrOfDigits; - } - - /* - * - */ - - private static boolean checkBitPositions(int firstBitPos, int lastBitPosExcl, int bitSize) { - if ((firstBitPos < 0) || (firstBitPos > lastBitPosExcl) || (lastBitPosExcl > bitSize)) { - throw new IllegalArgumentException( - "bit positions (first="+firstBitPos+",lastExcl="+lastBitPosExcl - +") must verify 0 <= first <= lastExcl <= "+bitSize); - } - return true; - } - - /** - * Common method for byte, short and int. - * Could be a bit faster to have specific methods for byte and short, - * but not much, and that would also make more messy (byte-)code. - * - * @param bitSize Must be in [0,32]. - */ - private static String toStringBits_0_32_bitPosAlreadyChecked( - int bitSize, - int bits, - int firstBitPos, - int lastBitPosExcl, - boolean bigEndian, - boolean padding) { - final int bitSizeM1 = bitSize-1; - final int lastBitPos = lastBitPosExcl-1; - if (padding) { - final int nbrOfChars = bitSize; - final char[] chars = new char[nbrOfChars]; - int bitIndex = bitSizeM1; - if (bigEndian) { - final int firstBitIndex = bitSizeM1-lastBitPos; - final int lastBitIndex = bitSizeM1-firstBitPos; - while (bitIndex > lastBitIndex) { - chars[bitSizeM1-bitIndex] = '_'; - --bitIndex; - } - while (bitIndex >= firstBitIndex) { - chars[bitSizeM1-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); - --bitIndex; - } - while (bitIndex >= 0) { - chars[bitSizeM1-bitIndex] = '_'; - --bitIndex; - } - } else { - while (bitIndex > lastBitPos) { - chars[bitIndex] = '_'; - --bitIndex; - } - while (bitIndex >= firstBitPos) { - chars[bitIndex] = (char)('0'+((bits>>bitIndex)&1)); - --bitIndex; - } - while (bitIndex >= 0) { - chars[bitIndex] = '_'; - --bitIndex; - } - } - return new String(chars); - } else { - final int nbrOfChars = (lastBitPosExcl - firstBitPos); - final char[] chars = new char[nbrOfChars]; - if (bigEndian) { - final int firstBitIndex = bitSizeM1-lastBitPos; - final int lastBitIndex = bitSizeM1-firstBitPos; - int bitIndex = lastBitIndex; - while (bitIndex >= firstBitIndex) { - chars[lastBitIndex-bitIndex] = (char)('0'+((bits>>bitIndex)&1)); - --bitIndex; - } - } else { - int bitIndex = lastBitPos; - while (bitIndex >= firstBitPos) { - chars[bitIndex-firstBitPos] = (char)('0'+((bits>>bitIndex)&1)); - --bitIndex; - } - } - return new String(chars); - } - } -} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/StrictFastMath.java b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/StrictFastMath.java deleted file mode 100644 index a61ac9772..000000000 --- a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/StrictFastMath.java +++ /dev/null @@ -1,2998 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.jafama; - -/** - * Strict versions of FastMath methods. - * Cf. README.txt for more info. - */ -public final strictfp class StrictFastMath extends CmnFastMath { - - /* - * We use strictfp for the whole class: - * - for simplicity, - * - to reduce strictfp/non-strictfp switching, which can add overhead, - * when these treatments are used from within strictfp code, - * - to make sure that we only use and return non-extended values, - * else if strictfp gets added later to some treatments they might then - * behave differently due to no longer being inlinable into FP-wide - * expressions, - * - to make sure we don't mistakenly not use it. - */ - - //-------------------------------------------------------------------------- - // CONFIGURATION - //-------------------------------------------------------------------------- - - private static final boolean USE_JDK_MATH = SFM_USE_JDK_MATH; - - private static final boolean USE_REDEFINED_LOG = SFM_USE_REDEFINED_LOG; - - private static final boolean USE_REDEFINED_SQRT = SFM_USE_REDEFINED_SQRT; - - private static final boolean USE_POWTABS_FOR_ASIN = SFM_USE_POWTABS_FOR_ASIN; - - //-------------------------------------------------------------------------- - // PUBLIC METHODS - //-------------------------------------------------------------------------- - - /* - * trigonometry - */ - - /** - * @param angle Angle in radians. - * @return Angle sine. - */ - public static double sin(double angle) { - if (USE_JDK_MATH) { - return StrictMath.sin(angle); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - if (angle > SIN_COS_MAX_VALUE_FOR_INT_MODULO) { - if (false) { - // Can give very bad relative error near PI (mod 2*PI). - angle = remainderTwoPi(angle); - if (angle < 0.0) { - angle = -angle; - negateResult = !negateResult; - } - } else { - final long remAndQuad = remainderPiO2(angle); - angle = decodeRemainder(remAndQuad); - final double sin; - final int q = decodeQuadrant(remAndQuad); - if (q == 0) { - sin = sin(angle); - } else if (q == 1) { - sin = cos(angle); - } else if (q == 2) { - sin = -sin(angle); - } else { - sin = -cos(angle); - } - return (negateResult ? -sin : sin); - } - } - // index: possibly outside tables range. - int index = (int)(angle * SIN_COS_INDEXER + 0.5); - double delta = (angle - index * SIN_COS_DELTA_HI) - index * SIN_COS_DELTA_LO; - // Making sure index is within tables range. - // Last value of each table is the same than first, - // so we ignore it (tabs size minus one) for modulo. - index &= (SIN_COS_TABS_SIZE-2); // index % (SIN_COS_TABS_SIZE-1) - double indexSin = MyTSinCos.sinTab[index]; - double indexCos = MyTSinCos.cosTab[index]; - double result = indexSin + delta * (indexCos + delta * (-indexSin * ONE_DIV_F2 + delta * (-indexCos * ONE_DIV_F3 + delta * indexSin * ONE_DIV_F4))); - return negateResult ? -result : result; - } - - /** - * Quick sin, with accuracy of about 1.6e-3 (PI/) - * for |angle| < 6588395.0 (Integer.MAX_VALUE * (2*PI/) - 2) - * (- 2 due to removing PI/2 before using cosine tab), - * and no accuracy at all for larger values. - * - * @param angle Angle in radians. - * @return Angle sine. - */ - public static double sinQuick(double angle) { - if (USE_JDK_MATH) { - return StrictMath.sin(angle); - } - return MyTSinCos.cosTab[((int)(Math.abs(angle-Math.PI/2) * SIN_COS_INDEXER + 0.5)) & (SIN_COS_TABS_SIZE-2)]; - } - - /** - * @param angle Angle in radians. - * @return Angle cosine. - */ - public static double cos(double angle) { - if (USE_JDK_MATH) { - return StrictMath.cos(angle); - } - angle = Math.abs(angle); - if (angle > SIN_COS_MAX_VALUE_FOR_INT_MODULO) { - if (false) { - // Can give very bad relative error near PI (mod 2*PI). - angle = remainderTwoPi(angle); - if (angle < 0.0) { - angle = -angle; - } - } else { - final long remAndQuad = remainderPiO2(angle); - angle = decodeRemainder(remAndQuad); - final double cos; - final int q = decodeQuadrant(remAndQuad); - if (q == 0) { - cos = cos(angle); - } else if (q == 1) { - cos = -sin(angle); - } else if (q == 2) { - cos = -cos(angle); - } else { - cos = sin(angle); - } - return cos; - } - } - // index: possibly outside tables range. - int index = (int)(angle * SIN_COS_INDEXER + 0.5); - double delta = (angle - index * SIN_COS_DELTA_HI) - index * SIN_COS_DELTA_LO; - // Making sure index is within tables range. - // Last value of each table is the same than first, - // so we ignore it (tabs size minus one) for modulo. - index &= (SIN_COS_TABS_SIZE-2); // index % (SIN_COS_TABS_SIZE-1) - double indexCos = MyTSinCos.cosTab[index]; - double indexSin = MyTSinCos.sinTab[index]; - return indexCos + delta * (-indexSin + delta * (-indexCos * ONE_DIV_F2 + delta * (indexSin * ONE_DIV_F3 + delta * indexCos * ONE_DIV_F4))); - } - - /** - * Quick cos, with accuracy of about 1.6e-3 (PI/) - * for |angle| < 6588397.0 (Integer.MAX_VALUE * (2*PI/)), - * and no accuracy at all for larger values. - * - * @param angle Angle in radians. - * @return Angle cosine. - */ - public static double cosQuick(double angle) { - if (USE_JDK_MATH) { - return StrictMath.cos(angle); - } - return MyTSinCos.cosTab[((int)(Math.abs(angle) * SIN_COS_INDEXER + 0.5)) & (SIN_COS_TABS_SIZE-2)]; - } - - /** - * Computes sine and cosine together. - * - * @param angle Angle in radians. - * @param cosine (out) Angle cosine. - * @return Angle sine. - */ - public static double sinAndCos(double angle, DoubleWrapper cosine) { - if (USE_JDK_MATH) { - cosine.value = StrictMath.cos(angle); - return StrictMath.sin(angle); - } - // Using the same algorithm than sin(double) method, - // and computing also cosine at the end. - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - if (angle > SIN_COS_MAX_VALUE_FOR_INT_MODULO) { - if (false) { - // Can give very bad relative error near PI (mod 2*PI). - angle = remainderTwoPi(angle); - if (angle < 0.0) { - angle = -angle; - negateResult = !negateResult; - } - } else { - final long remAndQuad = remainderPiO2(angle); - angle = decodeRemainder(remAndQuad); - final double sin; - final int q = decodeQuadrant(remAndQuad); - if (q == 0) { - sin = sin(angle); - cosine.value = cos(angle); - } else if (q == 1) { - sin = cos(angle); - cosine.value = -sin(angle); - } else if (q == 2) { - sin = -sin(angle); - cosine.value = -cos(angle); - } else { - sin = -cos(angle); - cosine.value = sin(angle); - } - return (negateResult ? -sin : sin); - } - } - int index = (int)(angle * SIN_COS_INDEXER + 0.5); - double delta = (angle - index * SIN_COS_DELTA_HI) - index * SIN_COS_DELTA_LO; - index &= (SIN_COS_TABS_SIZE-2); // index % (SIN_COS_TABS_SIZE-1) - double indexSin = MyTSinCos.sinTab[index]; - double indexCos = MyTSinCos.cosTab[index]; - // Could factor some multiplications (delta * factorials), but then is less accurate. - cosine.value = indexCos + delta * (-indexSin + delta * (-indexCos * ONE_DIV_F2 + delta * (indexSin * ONE_DIV_F3 + delta * indexCos * ONE_DIV_F4))); - double result = indexSin + delta * (indexCos + delta * (-indexSin * ONE_DIV_F2 + delta * (-indexCos * ONE_DIV_F3 + delta * indexSin * ONE_DIV_F4))); - return negateResult ? -result : result; - } - - /** - * Can have very bad relative error near +-PI/2, - * but of the same magnitude than the relative delta between - * StrictMath.tan(PI/2) and StrictMath.tan(nextDown(PI/2)). - * - * @param angle Angle in radians. - * @return Angle tangent. - */ - public static double tan(double angle) { - if (USE_JDK_MATH) { - return StrictMath.tan(angle); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - if (angle > TAN_MAX_VALUE_FOR_INT_MODULO) { - angle = remainderPi(angle); - if (angle < 0.0) { - angle = -angle; - negateResult = !negateResult; - } - } - // index: possibly outside tables range. - int index = (int)(angle * TAN_INDEXER + 0.5); - double delta = (angle - index * TAN_DELTA_HI) - index * TAN_DELTA_LO; - // Making sure index is within tables range. - // index modulo PI, i.e. 2*(virtual tab size minus one). - index &= (2*(TAN_VIRTUAL_TABS_SIZE-1)-1); // index % (2*(TAN_VIRTUAL_TABS_SIZE-1)) - // Here, index is in [0,2*(TAN_VIRTUAL_TABS_SIZE-1)-1], i.e. indicates an angle in [0,PI[. - if (index > (TAN_VIRTUAL_TABS_SIZE-1)) { - index = (2*(TAN_VIRTUAL_TABS_SIZE-1)) - index; - delta = -delta; - negateResult = !negateResult; - } - double result; - if (index < TAN_TABS_SIZE) { - result = MyTTan.tanTab[index] - + delta * (MyTTan.tanDer1DivF1Tab[index] - + delta * (MyTTan.tanDer2DivF2Tab[index] - + delta * (MyTTan.tanDer3DivF3Tab[index] - + delta * MyTTan.tanDer4DivF4Tab[index]))); - } else { // angle in ]TAN_MAX_VALUE_FOR_TABS,TAN_MAX_VALUE_FOR_INT_MODULO], or angle is NaN - // Using tan(angle) == 1/tan(PI/2-angle) formula: changing angle (index and delta), and inverting. - index = (TAN_VIRTUAL_TABS_SIZE-1) - index; - result = 1/(MyTTan.tanTab[index] - - delta * (MyTTan.tanDer1DivF1Tab[index] - - delta * (MyTTan.tanDer2DivF2Tab[index] - - delta * (MyTTan.tanDer3DivF3Tab[index] - - delta * MyTTan.tanDer4DivF4Tab[index])))); - } - return negateResult ? -result : result; - } - - /** - * @param value Value in [-1,1]. - * @return Value arcsine, in radians, in [-PI/2,PI/2]. - */ - public static double asin(double value) { - if (USE_JDK_MATH) { - return StrictMath.asin(value); - } - boolean negateResult = false; - if (value < 0.0) { - value = -value; - negateResult = true; - } - if (value <= ASIN_MAX_VALUE_FOR_TABS) { - int index = (int)(value * ASIN_INDEXER + 0.5); - double delta = value - index * ASIN_DELTA; - double result = MyTAsin.asinTab[index] - + delta * (MyTAsin.asinDer1DivF1Tab[index] - + delta * (MyTAsin.asinDer2DivF2Tab[index] - + delta * (MyTAsin.asinDer3DivF3Tab[index] - + delta * MyTAsin.asinDer4DivF4Tab[index]))); - return negateResult ? -result : result; - } else if (USE_POWTABS_FOR_ASIN && (value <= ASIN_MAX_VALUE_FOR_POWTABS)) { - int index = (int)(powFast(value * ASIN_POWTABS_ONE_DIV_MAX_VALUE, ASIN_POWTABS_POWER) * ASIN_POWTABS_SIZE_MINUS_ONE + 0.5); - double delta = value - MyTAsinPow.asinParamPowTab[index]; - double result = MyTAsinPow.asinPowTab[index] - + delta * (MyTAsinPow.asinDer1DivF1PowTab[index] - + delta * (MyTAsinPow.asinDer2DivF2PowTab[index] - + delta * (MyTAsinPow.asinDer3DivF3PowTab[index] - + delta * MyTAsinPow.asinDer4DivF4PowTab[index]))); - return negateResult ? -result : result; - } else { // value > ASIN_MAX_VALUE_FOR_TABS, or value is NaN - // This part is derived from fdlibm. - if (value < 1.0) { - double t = (1.0 - value)*0.5; - double p = t*(ASIN_PS0+t*(ASIN_PS1+t*(ASIN_PS2+t*(ASIN_PS3+t*(ASIN_PS4+t*ASIN_PS5))))); - double q = 1.0+t*(ASIN_QS1+t*(ASIN_QS2+t*(ASIN_QS3+t*ASIN_QS4))); - double s = sqrt(t); - double z = s+s*(p/q); - double result = ASIN_PIO2_HI-((z+z)-ASIN_PIO2_LO); - return negateResult ? -result : result; - } else { // value >= 1.0, or value is NaN - if (value == 1.0) { - return negateResult ? -Math.PI/2 : Math.PI/2; - } else { - return Double.NaN; - } - } - } - } - - /** - * If value is not NaN and is outside [-1,1] range, closest value in this range is used. - * - * @param value Value in [-1,1]. - * @return Value arcsine, in radians, in [-PI/2,PI/2]. - */ - public static double asinInRange(double value) { - if (value <= -1.0) { - return -Math.PI/2; - } else if (value >= 1.0) { - return Math.PI/2; - } else { - return asin(value); - } - } - - /** - * @param value Value in [-1,1]. - * @return Value arccosine, in radians, in [0,PI]. - */ - public static double acos(double value) { - if (USE_JDK_MATH) { - return StrictMath.acos(value); - } - return Math.PI/2 - asin(value); - } - - /** - * If value is not NaN and is outside [-1,1] range, - * closest value in this range is used. - * - * @param value Value in [-1,1]. - * @return Value arccosine, in radians, in [0,PI]. - */ - public static double acosInRange(double value) { - if (value <= -1.0) { - return Math.PI; - } else if (value >= 1.0) { - return 0.0; - } else { - return acos(value); - } - } - - /** - * @param value A double value. - * @return Value arctangent, in radians, in [-PI/2,PI/2]. - */ - public static double atan(double value) { - if (USE_JDK_MATH) { - return StrictMath.atan(value); - } - boolean negateResult = false; - if (value < 0.0) { - value = -value; - negateResult = true; - } - if (value == 1.0) { - // We want "exact" result for 1.0. - return negateResult ? -Math.PI/4 : Math.PI/4; - } else if (value <= ATAN_MAX_VALUE_FOR_TABS) { - int index = (int)(value * ATAN_INDEXER + 0.5); - double delta = value - index * ATAN_DELTA; - double result = MyTAtan.atanTab[index] - + delta * (MyTAtan.atanDer1DivF1Tab[index] - + delta * (MyTAtan.atanDer2DivF2Tab[index] - + delta * (MyTAtan.atanDer3DivF3Tab[index] - + delta * MyTAtan.atanDer4DivF4Tab[index]))); - return negateResult ? -result : result; - } else { // value > ATAN_MAX_VALUE_FOR_TABS, or value is NaN - // This part is derived from fdlibm. - if (value < TWO_POW_66) { - double x = -1/value; - double x2 = x*x; - double x4 = x2*x2; - double s1 = x2*(ATAN_AT0+x4*(ATAN_AT2+x4*(ATAN_AT4+x4*(ATAN_AT6+x4*(ATAN_AT8+x4*ATAN_AT10))))); - double s2 = x4*(ATAN_AT1+x4*(ATAN_AT3+x4*(ATAN_AT5+x4*(ATAN_AT7+x4*ATAN_AT9)))); - double result = ATAN_HI3-((x*(s1+s2)-ATAN_LO3)-x); - return negateResult ? -result : result; - } else { // value >= 2^66, or value is NaN - if (value != value) { - return Double.NaN; - } else { - return negateResult ? -Math.PI/2 : Math.PI/2; - } - } - } - } - - /** - * For special values for which multiple conventions could be adopted, - * behaves like StrictMath.atan2(double,double). - * - * @param y Coordinate on y axis. - * @param x Coordinate on x axis. - * @return Angle from x axis positive side to (x,y) position, in radians, in [-PI,PI]. - * Angle measure is positive when going from x axis to y axis (positive sides). - */ - public static double atan2(double y, double x) { - if (USE_JDK_MATH) { - return StrictMath.atan2(y,x); - } - /* - * Using sub-methods, to make method lighter for general case, - * and to avoid JIT-optimization crash on NaN. - */ - if (x > 0.0) { - if (y == 0.0) { - // +-0.0 - return y; - } - if (x == Double.POSITIVE_INFINITY) { - return atan2_pinf_yyy(y); - } else { - return atan(y/x); - } - } else if (x < 0.0) { - if (y == 0.0) { - return signFromBit(y) * Math.PI; - } - if (x == Double.NEGATIVE_INFINITY) { - return atan2_ninf_yyy(y); - } else if (y > 0.0) { - return Math.PI/2 - atan(x/y); - } else if (y < 0.0) { - return -Math.PI/2 - atan(x/y); - } else { - return Double.NaN; - } - } else { - return atan2_yyy_zeroOrNaN(y, x); - } - } - - /** - * Gives same result as StrictMath.toRadians for some particular values - * like 90.0, 180.0 or 360.0, but is faster (no division). - * - * @param angdeg Angle value in degrees. - * @return Angle value in radians. - */ - public static double toRadians(double angdeg) { - if (USE_JDK_MATH) { - return StrictMath.toRadians(angdeg); - } - return angdeg * (Math.PI/180); - } - - /** - * Gives same result as StrictMath.toDegrees for some particular values - * like Math.PI/2, Math.PI or 2*Math.PI, but is faster (no division). - * - * @param angrad Angle value in radians. - * @return Angle value in degrees. - */ - public static double toDegrees(double angrad) { - if (USE_JDK_MATH) { - return StrictMath.toDegrees(angrad); - } - return angrad * (180/Math.PI); - } - - /** - * @param sign Sign of the angle: true for positive, false for negative. - * @param degrees Degrees, in [0,180]. - * @param minutes Minutes, in [0,59]. - * @param seconds Seconds, in [0.0,60.0[. - * @return Angle in radians. - */ - public static double toRadians(boolean sign, int degrees, int minutes, double seconds) { - return toRadians(toDegrees(sign, degrees, minutes, seconds)); - } - - /** - * @param sign Sign of the angle: true for positive, false for negative. - * @param degrees Degrees, in [0,180]. - * @param minutes Minutes, in [0,59]. - * @param seconds Seconds, in [0.0,60.0[. - * @return Angle in degrees. - */ - public static double toDegrees(boolean sign, int degrees, int minutes, double seconds) { - double signFactor = sign ? 1.0 : -1.0; - return signFactor * (degrees + (1.0/60)*(minutes + (1.0/60)*seconds)); - } - - /** - * @param angrad Angle in radians. - * @param degrees (out) Degrees, in [0,180]. - * @param minutes (out) Minutes, in [0,59]. - * @param seconds (out) Seconds, in [0.0,60.0[. - * @return true if the resulting angle in [-180deg,180deg] is positive, false if it is negative. - */ - public static boolean toDMS(double angrad, IntWrapper degrees, IntWrapper minutes, DoubleWrapper seconds) { - // Computing longitude DMS. - double tmp = toDegrees(normalizeMinusPiPi(angrad)); - boolean isNeg = (tmp < 0.0); - if (isNeg) { - tmp = -tmp; - } - degrees.value = (int)tmp; - tmp = (tmp-degrees.value)*60.0; - minutes.value = (int)tmp; - seconds.value = Math.min((tmp-minutes.value)*60.0,DOUBLE_BEFORE_60); - return !isNeg; - } - - /** - * NB: Since 2*Math.PI < 2*PI, a span of 2*Math.PI does not mean full angular range. - * ex.: isInClockwiseDomain(0.0, 2*Math.PI, -1e-20) returns false. - * ---> For full angular range, use a span > 2*Math.PI, like 2*PI_SUP constant of this class. - * - * @param startAngRad An angle, in radians. - * @param angSpanRad An angular span, >= 0.0, in radians. - * @param angRad An angle, in radians. - * @return true if angRad is in the clockwise angular domain going from startAngRad, over angSpanRad, - * extremities included, false otherwise. - */ - public static boolean isInClockwiseDomain(double startAngRad, double angSpanRad, double angRad) { - if (Math.abs(angRad) < -TWO_MATH_PI_IN_MINUS_PI_PI) { - // special case for angular values of small magnitude - if (angSpanRad <= 2*Math.PI) { - if (angSpanRad < 0.0) { - // empty domain - return false; - } - // angSpanRad is in [0,2*PI] - startAngRad = normalizeMinusPiPi(startAngRad); - double endAngRad = normalizeMinusPiPi(startAngRad + angSpanRad); - if (startAngRad <= endAngRad) { - return (angRad >= startAngRad) && (angRad <= endAngRad); - } else { - return (angRad >= startAngRad) || (angRad <= endAngRad); - } - } else { // angSpanRad > 2*Math.PI, or is NaN - return (angSpanRad == angSpanRad); - } - } else { - // general case - return (normalizeZeroTwoPi(angRad - startAngRad) <= angSpanRad); - } - } - - /* - * hyperbolic trigonometry - */ - - /** - * Some properties of sinh(x) = (exp(x)-exp(-x))/2: - * 1) defined on ]-Infinity,+Infinity[ - * 2) result in ]-Infinity,+Infinity[ - * 3) sinh(x) = -sinh(-x) (implies sinh(0) = 0) - * 4) sinh(epsilon) ~= epsilon - * 5) lim(sinh(x),x->+Infinity) = +Infinity - * (y increasing exponentially faster than x) - * 6) reaches +Infinity (double overflow) for x >= 710.475860073944, - * i.e. a bit further than exp(x) - * - * @param value A double value. - * @return Value hyperbolic sine. - */ - public static double sinh(double value) { - if (USE_JDK_MATH) { - return StrictMath.sinh(value); - } - // sinh(x) = (exp(x)-exp(-x))/2 - double h; - if (value < 0.0) { - value = -value; - h = -0.5; - } else { - h = 0.5; - } - if (value < 22.0) { - if (value < TWO_POW_N28) { - return (h < 0.0) ? -value : value; - } else { - // sinh(x) - // = (exp(x)-exp(-x))/2 - // = (exp(x)-1/exp(x))/2 - // = (expm1(x) + 1 - 1/(expm1(x)+1))/2 - // = (expm1(x) + (expm1(x)+1)/(expm1(x)+1) - 1/(expm1(x)+1))/2 - // = (expm1(x) + expm1(x)/(expm1(x)+1))/2 - double t = expm1(value); - // Might be more accurate, if value < 1: return h*((t+t)-t*t/(t+1.0)). - return h * (t + t/(t+1.0)); - } - } else if (value < LOG_DOUBLE_MAX_VALUE) { - return h * exp(value); - } else { - double t = exp(value*0.5); - return (h*t)*t; - } - } - - /** - * Some properties of cosh(x) = (exp(x)+exp(-x))/2: - * 1) defined on ]-Infinity,+Infinity[ - * 2) result in [1,+Infinity[ - * 3) cosh(0) = 1 - * 4) cosh(x) = cosh(-x) - * 5) lim(cosh(x),x->+Infinity) = +Infinity - * (y increasing exponentially faster than x) - * 6) reaches +Infinity (double overflow) for x >= 710.475860073944, - * i.e. a bit further than exp(x) - * - * @param value A double value. - * @return Value hyperbolic cosine. - */ - public static double cosh(double value) { - if (USE_JDK_MATH) { - return StrictMath.cosh(value); - } - // cosh(x) = (exp(x)+exp(-x))/2 - if (value < 0.0) { - value = -value; - } - if (value < LOG_TWO_POW_27) { - if (value < TWO_POW_N27) { - // cosh(x) - // = (exp(x)+exp(-x))/2 - // = ((1+x+x^2/2!+...) + (1-x+x^2/2!-...))/2 - // = 1+x^2/2!+x^4/4!+... - // For value of x small in magnitude, the sum of the terms does not add to 1. - return 1; - } else { - // cosh(x) - // = (exp(x)+exp(-x))/2 - // = (exp(x)+1/exp(x))/2 - double t = exp(value); - return 0.5 * (t+1/t); - } - } else if (value < LOG_DOUBLE_MAX_VALUE) { - return 0.5 * exp(value); - } else { - double t = exp(value*0.5); - return (0.5*t)*t; - } - } - - /** - * Much more accurate than cosh(value)-1, - * for arguments (and results) close to zero. - * - * coshm1(-0.0) = -0.0, for homogeneity with - * acosh1p(-0.0) = -0.0. - * - * @param value A double value. - * @return Value hyperbolic cosine, minus 1. - */ - public static double coshm1(double value) { - // cosh(x)-1 = (exp(x)+exp(-x))/2 - 1 - if (value < 0.0) { - value = -value; - } - if (value < LOG_TWO_POW_27) { - if (value < TWO_POW_N27) { - if (value == 0.0) { - // +-0.0 - return value; - } - // Using (expm1(x)+expm1(-x))/2 - // is not accurate for tiny values, - // for expm1 results are of higher - // magnitude than the result and - // of different signs, such as their - // sum is not accurate. - // cosh(x) - 1 - // = (exp(x)+exp(-x))/2 - 1 - // = ((1+x+x^2/2!+...) + (1-x+x^2/2!-...))/2 - 1 - // = x^2/2!+x^4/4!+... - // ~= x^2 * (1/2 + x^2 * 1/24) - // = x^2 * 0.5 (since x < 2^-27) - return 0.5 * value*value; - } else { - // cosh(x) - 1 - // = (exp(x)+exp(-x))/2 - 1 - // = (exp(x)-1+exp(-x)-1)/2 - // = (expm1(x)+expm1(-x))/2 - return 0.5 * (expm1(value)+expm1(-value)); - } - } else if (value < LOG_DOUBLE_MAX_VALUE) { - return 0.5 * exp(value) - 1.0; - } else { - // No need to subtract 1 from result. - double t = exp(value*0.5); - return (0.5*t)*t; - } - } - - /** - * Computes hyperbolic sine and hyperbolic cosine together. - * - * @param value A double value. - * @param hcosine (out) Value hyperbolic cosine. - * @return Value hyperbolic sine. - */ - public static double sinhAndCosh(double value, DoubleWrapper hcosine) { - if (USE_JDK_MATH) { - hcosine.value = StrictMath.cosh(value); - return StrictMath.sinh(value); - } - // Mixup of sinh and cosh treatments: if you modify them, - // you might want to also modify this. - double h; - if (value < 0.0) { - value = -value; - h = -0.5; - } else { - h = 0.5; - } - final double hsine; - // LOG_TWO_POW_27 = 18.714973875118524 - if (value < LOG_TWO_POW_27) { // test from cosh - // sinh - if (value < TWO_POW_N28) { - hsine = (h < 0.0) ? -value : value; - } else { - double t = expm1(value); - hsine = h * (t + t/(t+1.0)); - } - // cosh - if (value < TWO_POW_N27) { - hcosine.value = 1; - } else { - double t = exp(value); - hcosine.value = 0.5 * (t+1/t); - } - } else if (value < 22.0) { // test from sinh - // Here, value is in [18.714973875118524,22.0[. - double t = expm1(value); - hsine = h * (t + t/(t+1.0)); - hcosine.value = 0.5 * (t+1.0); - } else { - if (value < LOG_DOUBLE_MAX_VALUE) { - hsine = h * exp(value); - } else { - double t = exp(value*0.5); - hsine = (h*t)*t; - } - hcosine.value = Math.abs(hsine); - } - return hsine; - } - - /** - * Some properties of tanh(x) = sinh(x)/cosh(x) = (exp(2*x)-1)/(exp(2*x)+1): - * 1) defined on ]-Infinity,+Infinity[ - * 2) result in ]-1,1[ - * 3) tanh(x) = -tanh(-x) (implies tanh(0) = 0) - * 4) tanh(epsilon) ~= epsilon - * 5) lim(tanh(x),x->+Infinity) = 1 - * 6) reaches 1 (double loss of precision) for x = 19.061547465398498 - * - * @param value A double value. - * @return Value hyperbolic tangent. - */ - public static double tanh(double value) { - if (USE_JDK_MATH) { - return StrictMath.tanh(value); - } - // tanh(x) = sinh(x)/cosh(x) - // = (exp(x)-exp(-x))/(exp(x)+exp(-x)) - // = (exp(2*x)-1)/(exp(2*x)+1) - boolean negateResult = false; - if (value < 0.0) { - value = -value; - negateResult = true; - } - double z; - if (value < TANH_1_THRESHOLD) { - if (value < TWO_POW_N55) { - return negateResult ? -value*(1.0-value) : value*(1.0+value); - } else if (value >= 1) { - z = 1.0-2.0/(expm1(value+value)+2.0); - } else { - double t = expm1(-(value+value)); - z = -t/(t+2.0); - } - } else { - z = (value != value) ? Double.NaN : 1.0; - } - return negateResult ? -z : z; - } - - /** - * Some properties of asinh(x) = log(x + sqrt(x^2 + 1)) - * 1) defined on ]-Infinity,+Infinity[ - * 2) result in ]-Infinity,+Infinity[ - * 3) asinh(x) = -asinh(-x) (implies asinh(0) = 0) - * 4) asinh(epsilon) ~= epsilon - * 5) lim(asinh(x),x->+Infinity) = +Infinity - * (y increasing logarithmically slower than x) - * - * @param value A double value. - * @return Value hyperbolic arcsine. - */ - public static double asinh(double value) { - // asinh(x) = log(x + sqrt(x^2 + 1)) - boolean negateResult = false; - if (value < 0.0) { - value = -value; - negateResult = true; - } - double result; - // (about) smallest possible for - // non-log1p case to be accurate. - if (value < ASINH_LOG1P_THRESHOLD) { - // Around this range, FDLIBM uses - // log1p(value+value*value/(1+sqrt(value*value+1))), - // but it's slower, so we don't use it. - /* - * If x is close to zero, log argument is close to 1, - * so to avoid precision loss we use log1p(double), - * with - * (1+x)^p = 1 + p * x + (p*(p-1))/2! * x^2 + (p*(p-1)*(p-2))/3! * x^3 + ... - * (1+x)^p = 1 + p * x * (1 + (p-1)/2 * x * (1 + (p-2)/3 * x + ...) - * (1+x)^0.5 = 1 + 0.5 * x * (1 + (0.5-1)/2 * x * (1 + (0.5-2)/3 * x + ...) - * (1+x^2)^0.5 = 1 + 0.5 * x^2 * (1 + (0.5-1)/2 * x^2 * (1 + (0.5-2)/3 * x^2 + ...) - * x + (1+x^2)^0.5 = 1 + x * (1 + 0.5 * x * (1 + (0.5-1)/2 * x^2 * (1 + (0.5-2)/3 * x^2 + ...)) - * so - * asinh(x) = log1p(x * (1 + 0.5 * x * (1 + (0.5-1)/2 * x^2 * (1 + (0.5-2)/3 * x^2 + ...))) - */ - final double x = value; - final double x2 = x*x; - // Enough terms for good accuracy, - // given our threshold. - final double argLog1p = (x * - (1 + 0.5 * x - * (1 + (0.5-1)/2 * x2 - * (1 + (0.5-2)/3 * x2 - * (1 + (0.5-3)/4 * x2 - * (1 + (0.5-4)/5 * x2 - )))))); - result = log1p(argLog1p); - } else if (value < ASINH_ACOSH_SQRT_ELISION_THRESHOLD) { - // Around this range, FDLIBM uses - // log(2*value+1/(value+sqrt(value*value+1))), - // but it involves an additional division - // so we don't use it. - result = log(value + sqrt(value*value + 1.0)); - } else { - // log(2*value) would overflow for value > Double.MAX_VALUE/2, - // so we compute otherwise. - result = LOG_2 + log(value); - } - return negateResult ? -result : result; - } - - /** - * Some properties of acosh(x) = log(x + sqrt(x^2 - 1)): - * 1) defined on [1,+Infinity[ - * 2) result in ]0,+Infinity[ (by convention, since cosh(x) = cosh(-x)) - * 3) acosh(1) = 0 - * 4) acosh(1+epsilon) ~= log(1 + sqrt(2*epsilon)) ~= sqrt(2*epsilon) - * 5) lim(acosh(x),x->+Infinity) = +Infinity - * (y increasing logarithmically slower than x) - * - * @param value A double value. - * @return Value hyperbolic arccosine. - */ - public static double acosh(double value) { - if (!(value > 1.0)) { - // NaN, or value <= 1 - if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { - return (value < 1.0) ? Double.NaN : value - 1.0; - } else { - return (value == 1.0) ? 0.0 : Double.NaN; - } - } - double result; - if (value < ASINH_ACOSH_SQRT_ELISION_THRESHOLD) { - // Around this range, FDLIBM uses - // log(2*value-1/(value+sqrt(value*value-1))), - // but it involves an additional division - // so we don't use it. - result = log(value + sqrt(value*value - 1.0)); - } else { - // log(2*value) would overflow for value > Double.MAX_VALUE/2, - // so we compute otherwise. - result = LOG_2 + log(value); - } - return result; - } - - /** - * Much more accurate than acosh(1+value), - * for arguments (and results) close to zero. - * - * acosh1p(-0.0) = -0.0, for homogeneity with - * sqrt(-0.0) = -0.0, which looks about the same - * near 0. - * - * @param value A double value. - * @return Hyperbolic arccosine of (1+value). - */ - public static double acosh1p(double value) { - if (!(value > 0.0)) { - // NaN, or value <= 0. - // If value is -0.0, returning -0.0. - if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { - return (value < 0.0) ? Double.NaN : value; - } else { - return (value == 0.0) ? value : Double.NaN; - } - } - double result; - if (value < (ASINH_ACOSH_SQRT_ELISION_THRESHOLD-1)) { - // acosh(1+x) - // = log((1+x) + sqrt((1+x)^2 - 1)) - // = log(1 + x + sqrt(1 + 2*x + x^2 - 1)) - // = log1p(x + sqrt(2*x + x^2)) - // = log1p(x + sqrt(x * (2 + x)) - result = log1p(value + sqrt(value * (2 + value))); - } else { - result = LOG_2 + log(1+value); - } - return result; - } - - /** - * Some properties of atanh(x) = log((1+x)/(1-x))/2: - * 1) defined on ]-1,1[ - * 2) result in ]-Infinity,+Infinity[ - * 3) atanh(-1) = -Infinity (by continuity) - * 4) atanh(1) = +Infinity (by continuity) - * 5) atanh(epsilon) ~= epsilon - * 6) lim(atanh(x),x->1) = +Infinity - * - * @param value A double value. - * @return Value hyperbolic arctangent. - */ - public static double atanh(double value) { - boolean negateResult = false; - if (value < 0.0) { - value = -value; - negateResult = true; - } - double result; - if (!(value < 1.0)) { - // NaN, or value >= 1 - if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { - result = (value > 1.0) ? Double.NaN : Double.POSITIVE_INFINITY + value; - } else { - result = (value == 1.0) ? Double.POSITIVE_INFINITY : Double.NaN; - } - } else { - // For value < 0.5, FDLIBM uses - // 0.5 * log1p((value+value) + (value+value)*value/(1-value)), - // instead, but this is good enough for us. - // atanh(x) - // = log((1+x)/(1-x))/2 - // = log((1-x+2x)/(1-x))/2 - // = log1p(2x/(1-x))/2 - result = 0.5 * log1p((value+value)/(1.0-value)); - } - return negateResult ? -result : result; - } - - /* - * exponentials - */ - - /** - * @param value A double value. - * @return e^value. - */ - public static double exp(double value) { - if (USE_JDK_MATH) { - return StrictMath.exp(value); - } - // exp(x) = exp([x])*exp(y) - // with [x] the integer part of x, and y = x-[x] - // ===> - // We find an approximation of y, called z. - // ===> - // exp(x) = exp([x])*(exp(z)*exp(epsilon)) - // with epsilon = y - z - // ===> - // We have exp([x]) and exp(z) pre-computed in tables, we "just" have to compute exp(epsilon). - // - // We use the same indexing (cast to int) to compute x integer part and the - // table index corresponding to z, to avoid two int casts. - // Also, to optimize index multiplication and division, we use powers of two, - // so that we can do it with bits shifts. - - if (value > EXP_OVERFLOW_LIMIT) { - return Double.POSITIVE_INFINITY; - } else if (!(value >= EXP_UNDERFLOW_LIMIT)) { - return (value != value) ? Double.NaN : 0.0; - } - - final int indexes = (int)(value*EXP_LO_INDEXING); - - final int valueInt; - if (indexes >= 0) { - valueInt = (indexes>>EXP_LO_INDEXING_DIV_SHIFT); - } else { - valueInt = -((-indexes)>>EXP_LO_INDEXING_DIV_SHIFT); - } - final double hiTerm = MyTExp.expHiTab[valueInt-(int)EXP_UNDERFLOW_LIMIT]; - - final int zIndex = indexes - (valueInt< 0.0) { - if (value == Double.POSITIVE_INFINITY) { - return Double.POSITIVE_INFINITY; - } - - // For normal values not close to 1.0, we use the following formula: - // log(value) - // = log(2^exponent*1.mantissa) - // = log(2^exponent) + log(1.mantissa) - // = exponent * log(2) + log(1.mantissa) - // = exponent * log(2) + log(1.mantissaApprox) + log(1.mantissa/1.mantissaApprox) - // = exponent * log(2) + log(1.mantissaApprox) + log(1+epsilon) - // = exponent * log(2) + log(1.mantissaApprox) + epsilon-epsilon^2/2+epsilon^3/3-epsilon^4/4+... - // with: - // 1.mantissaApprox <= 1.mantissa, - // log(1.mantissaApprox) in table, - // epsilon = (1.mantissa/1.mantissaApprox)-1 - // - // To avoid bad relative error for small results, - // values close to 1.0 are treated aside, with the formula: - // log(x) = z*(2+z^2*((2.0/3)+z^2*((2.0/5))+z^2*((2.0/7))+...))) - // with z=(x-1)/(x+1) - - double h; - if (value > 0.95) { - if (value < 1.14) { - double z = (value-1.0)/(value+1.0); - double z2 = z*z; - return z*(2+z2*((2.0/3)+z2*((2.0/5)+z2*((2.0/7)+z2*((2.0/9)+z2*((2.0/11))))))); - } - h = 0.0; - } else if (value < DOUBLE_MIN_NORMAL) { - // Ensuring value is normal. - value *= TWO_POW_52; - // log(x*2^52) - // = log(x)-ln(2^52) - // = log(x)-52*ln(2) - h = -52*LOG_2; - } else { - h = 0.0; - } - - int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); - int valueExp = (valueBitsHi>>20)-MAX_DOUBLE_EXPONENT; - // Getting the first LOG_BITS bits of the mantissa. - int xIndex = ((valueBitsHi<<12)>>>(32-LOG_BITS)); - - // 1.mantissa/1.mantissaApprox - 1 - double z = (value * twoPowNormalOrSubnormal(-valueExp)) * MyTLog.logXInvTab[xIndex] - 1; - - z *= (1-z*((1.0/2)-z*((1.0/3)))); - - return h + valueExp * LOG_2 + (MyTLog.logXLogTab[xIndex] + z); - - } else if (value == 0.0) { - return Double.NEGATIVE_INFINITY; - } else { // value < 0.0, or value is NaN - return Double.NaN; - } - } - - /** - * Quick log, with a max relative error of about 1.9e-3 - * for values in ]Double.MIN_NORMAL,+Infinity[, and - * worse accuracy outside this range. - * - * @param value A double value, in ]0,+Infinity[ (strictly positive and finite). - * @return Value logarithm (base e). - */ - public static double logQuick(double value) { - if (USE_JDK_MATH) { - return StrictMath.log(value); - } - /* - * Inverse of Schraudolph's method for exp, is very inaccurate near 1, - * and not that fast (even using floats), especially with added if's - * to deal with values near 1, so we don't use it, and use a simplified - * version of our log's redefined algorithm. - */ - - // Simplified version of log's redefined algorithm: - // log(value) ~= exponent * log(2) + log(1.mantissaApprox) - - double h; - if (value > 0.87) { - if (value < 1.16) { - return 2.0 * (value-1.0)/(value+1.0); - } - h = 0.0; - } else if (value < DOUBLE_MIN_NORMAL) { - value *= TWO_POW_52; - h = -52*LOG_2; - } else { - h = 0.0; - } - - int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); - int valueExp = (valueBitsHi>>20)-MAX_DOUBLE_EXPONENT; - int xIndex = ((valueBitsHi<<12)>>>(32-LOG_BITS)); - - return h + valueExp * LOG_2 + MyTLog.logXLogTab[xIndex]; - } - - /** - * @param value A double value. - * @return Value logarithm (base 10). - */ - public static double log10(double value) { - if (USE_JDK_MATH || (!USE_REDEFINED_LOG)) { - return StrictMath.log10(value); - } - // INV_LOG_10 is < 1, but there is no risk of log(double) - // overflow (positive or negative) while the end result shouldn't, - // since log(Double.MIN_VALUE) and log(Double.MAX_VALUE) have - // magnitudes of just a few hundreds. - return log(value) * INV_LOG_10; - } - - /** - * Much more accurate than log(1+value), - * for arguments (and results) close to zero. - * - * @param value A double value. - * @return Logarithm (base e) of (1+value). - */ - public static double log1p(double value) { - if (USE_JDK_MATH) { - return StrictMath.log1p(value); - } - if (false) { - // This also works. Simpler but a bit slower. - if (value == Double.POSITIVE_INFINITY) { - return Double.POSITIVE_INFINITY; - } - double valuePlusOne = 1+value; - if (valuePlusOne == 1.0) { - return value; - } else { - return log(valuePlusOne)*(value/(valuePlusOne-1.0)); - } - } - if (value > -1.0) { - if (value == Double.POSITIVE_INFINITY) { - return Double.POSITIVE_INFINITY; - } - - // ln'(x) = 1/x - // so - // log(x+epsilon) ~= log(x) + epsilon/x - // - // Let u be 1+value rounded: - // 1+value = u+epsilon - // - // log(1+value) - // = log(u+epsilon) - // ~= log(u) + epsilon/value - // We compute log(u) as done in log(double), and then add the corrective term. - - double valuePlusOne = 1.0+value; - if (valuePlusOne == 1.0) { - return value; - } else if (Math.abs(value) < 0.15) { - double z = value/(value+2.0); - double z2 = z*z; - return z*(2+z2*((2.0/3)+z2*((2.0/5)+z2*((2.0/7)+z2*((2.0/9)+z2*((2.0/11))))))); - } - - int valuePlusOneBitsHi = (int)(Double.doubleToRawLongBits(valuePlusOne)>>32) & 0x7FFFFFFF; - int valuePlusOneExp = (valuePlusOneBitsHi>>20)-MAX_DOUBLE_EXPONENT; - // Getting the first LOG_BITS bits of the mantissa. - int xIndex = ((valuePlusOneBitsHi<<12)>>>(32-LOG_BITS)); - - // 1.mantissa/1.mantissaApprox - 1 - double z = (valuePlusOne * twoPowNormalOrSubnormal(-valuePlusOneExp)) * MyTLog.logXInvTab[xIndex] - 1; - - z *= (1-z*((1.0/2)-z*(1.0/3))); - - // Adding epsilon/valuePlusOne to z, - // with - // epsilon = value - (valuePlusOne-1) - // (valuePlusOne + epsilon ~= 1+value (not rounded)) - - return valuePlusOneExp * LOG_2 + MyTLog.logXLogTab[xIndex] + (z + (value - (valuePlusOne-1))/valuePlusOne); - } else if (value == -1.0) { - return Double.NEGATIVE_INFINITY; - } else { // value < -1.0, or value is NaN - return Double.NaN; - } - } - - /* - * powers - */ - - /** - * 1e-13ish accuracy or better on whole double range. - * - * @param value A double value. - * @param power A power. - * @return value^power. - */ - public static double pow(double value, double power) { - if (USE_JDK_MATH) { - return StrictMath.pow(value,power); - } - if (power == 0.0) { - return 1.0; - } else if (power == 1.0) { - return value; - } - if (value <= 0.0) { - // powerInfo: 0 if not integer, 1 if even integer, -1 if odd integer - int powerInfo; - if (Math.abs(power) >= (TWO_POW_52*2)) { - // The binary digit just before comma is outside mantissa, - // thus it is always 0: power is an even integer. - powerInfo = 1; - } else { - // If power's magnitude permits, we cast into int instead of into long, - // as it is faster. - if (Math.abs(power) <= (double)Integer.MAX_VALUE) { - int powerAsInt = (int)power; - if (power == (double)powerAsInt) { - powerInfo = ((powerAsInt & 1) == 0) ? 1 : -1; - } else { // power is not an integer (and not NaN, due to test against Integer.MAX_VALUE) - powerInfo = 0; - } - } else { - long powerAsLong = (long)power; - if (power == (double)powerAsLong) { - powerInfo = ((powerAsLong & 1) == 0) ? 1 : -1; - } else { // power is not an integer, or is NaN - if (power != power) { - return Double.NaN; - } - powerInfo = 0; - } - } - } - - if (value == 0.0) { - if (power < 0.0) { - return (powerInfo < 0) ? 1/value : Double.POSITIVE_INFINITY; - } else { // power > 0.0 (0 and NaN cases already treated) - return (powerInfo < 0) ? value : 0.0; - } - } else { // value < 0.0 - if (value == Double.NEGATIVE_INFINITY) { - if (powerInfo < 0) { // power odd integer - return (power < 0.0) ? -0.0 : Double.NEGATIVE_INFINITY; - } else { // power even integer, or not an integer - return (power < 0.0) ? 0.0 : Double.POSITIVE_INFINITY; - } - } else { - return (powerInfo == 0) ? Double.NaN : powerInfo * exp(power*log(-value)); - } - } - } else { // value > 0.0, or value is NaN - return exp(power*log(value)); - } - } - - /** - * Quick pow, with a max relative error of about 1e-2 - * for value >= Double.MIN_NORMAL and 1e-10 < |value^power| < 1e10, - * of about 6e-2 for value >= Double.MIN_NORMAL and 1e-40 < |value^power| < 1e40, - * and worse accuracy otherwise. - * - * @param value A double value, in ]0,+Infinity[ (strictly positive and finite). - * @param power A double value. - * @return value^power. - */ - public static double powQuick(double value, double power) { - if (USE_JDK_MATH) { - return StrictMath.pow(value,power); - } - return exp(power*logQuick(value)); - } - - /** - * This treatment is somehow accurate for low values of |power|, - * and for |power*getExponent(value)| < 1023 or so (to stay away - * from double extreme magnitudes (large and small)). - * - * @param value A double value. - * @param power A power. - * @return value^power. - */ - public static double powFast(double value, int power) { - if (USE_JDK_MATH) { - return StrictMath.pow(value,power); - } - if (power < 3) { - if (power < 0) { - // Opposite of Integer.MIN_VALUE does not exist as int. - if (power == Integer.MIN_VALUE) { - // Integer.MAX_VALUE = -(power+1) - return 1.0/(powFast(value,Integer.MAX_VALUE) * value); - } else { - return 1.0/powFast(value,-power); - } - } else { - // Here, power is in [0,2]. - if (power == 2) { // Most common case first. - return value * value; - } else if (power == 0) { - return 1.0; - } else { // power == 1 - return value; - } - } - } else { // power >= 4 - double oddRemains = 1.0; - // If power <= 5, faster to finish outside the loop. - while (power > 5) { - // Test if power is odd. - if ((power & 1) != 0) { - oddRemains *= value; - } - value *= value; - power >>= 1; // power = power / 2 - } - // Here, power is in [3,5]. - if (power == 3) { - return oddRemains * value * value * value; - } else { // power in [4,5]. - double v2 = value * value; - if (power == 4) { - return oddRemains * v2 * v2; - } else { // power == 5 - return oddRemains * v2 * v2 * value; - } - } - } - } - - /** - * @param value A float value. - * @return value*value. - */ - public static float pow2(float value) { - return value*value; - } - - /** - * @param value A double value. - * @return value*value. - */ - public static double pow2(double value) { - return value*value; - } - - /** - * @param value A float value. - * @return value*value*value. - */ - public static float pow3(float value) { - return value*value*value; - } - - /** - * @param value A double value. - * @return value*value*value. - */ - public static double pow3(double value) { - return value*value*value; - } - - /* - * roots - */ - - /** - * @param value A double value. - * @return Value square root. - */ - public static double sqrt(double value) { - if (USE_JDK_MATH || (!USE_REDEFINED_SQRT)) { - return StrictMath.sqrt(value); - } - // See cbrt for comments, sqrt uses the same ideas. - - if (!(value > 0.0)) { // value <= 0.0, or value is NaN - if (ANTI_JIT_OPTIM_CRASH_ON_NAN) { - return (value < 0.0) ? Double.NaN : value; - } else { - return (value == 0.0) ? value : Double.NaN; - } - } else if (value == Double.POSITIVE_INFINITY) { - return Double.POSITIVE_INFINITY; - } - - double h; - if (value < DOUBLE_MIN_NORMAL) { - value *= TWO_POW_52; - h = 2*TWO_POW_N26; - } else { - h = 2.0; - } - - int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); - int valueExponentIndex = (valueBitsHi>>20)+(-MAX_DOUBLE_EXPONENT-MIN_DOUBLE_EXPONENT); - int xIndex = ((valueBitsHi<<12)>>>(32-SQRT_LO_BITS)); - - double result = MyTSqrt.sqrtXSqrtHiTab[valueExponentIndex] * MyTSqrt.sqrtXSqrtLoTab[xIndex]; - double slope = MyTSqrt.sqrtSlopeHiTab[valueExponentIndex] * MyTSqrt.sqrtSlopeLoTab[xIndex]; - value *= 0.25; - - result += (value - result * result) * slope; - result += (value - result * result) * slope; - return h*(result + (value - result * result) * slope); - } - - /** - * Quick sqrt, with with a max relative error of about 3.41e-2 - * for values in [Double.MIN_NORMAL,Double.MAX_VALUE], and worse - * accuracy outside this range. - * - * @param value A double value. - * @return Value square root. - */ - public static double sqrtQuick(double value) { - if (USE_JDK_MATH) { - return StrictMath.sqrt(value); - } - final long bits = Double.doubleToRawLongBits(value); - /* - * Constant determined empirically, using a random-based metaheuristic. - * Should be possible to find a better one. - */ - return Double.longBitsToDouble((bits+4606859074900000000L)>>>1); - } - - /** - * Quick inverse of square root, with a max relative error of about 3.44e-2 - * for values in [Double.MIN_NORMAL,Double.MAX_VALUE], and worse accuracy - * outside this range. - * - * This implementation uses zero step of Newton's method. - * Here are the max relative errors on [Double.MIN_NORMAL,Double.MAX_VALUE] - * depending on number of steps, if you want to copy-paste this code - * and use your own number: - * n=0: about 3.44e-2 - * n=1: about 1.75e-3 - * n=2: about 4.6e-6 - * n=3: about 3.17e-11 - * n=4: about 3.92e-16 - * n=5: about 3.03e-16 - * - * @param value A double value. - * @return Inverse of value square root. - */ - public static double invSqrtQuick(double value) { - if (USE_JDK_MATH) { - return 1/StrictMath.sqrt(value); - } - /* - * http://en.wikipedia.org/wiki/Fast_inverse_square_root - */ - if (false) { - // With one Newton step (much slower than - // 1/Math.sqrt(double) if not optimized). - final double halfInitial = value * 0.5; - long bits = Double.doubleToRawLongBits(value); - // If n=0, 6910474759270000000L might be better (3.38e-2 max relative error). - bits = 0x5FE6EB50C7B537A9L - (bits>>1); - value = Double.longBitsToDouble(bits); - value = value * (1.5 - halfInitial * value * value); // Newton step, can repeat. - return value; - } else { - return Double.longBitsToDouble(0x5FE6EB50C7B537A9L - (Double.doubleToRawLongBits(value)>>1)); - } - } - - /** - * @param value A double value. - * @return Value cubic root. - */ - public static double cbrt(double value) { - if (USE_JDK_MATH) { - return StrictMath.cbrt(value); - } - double h; - if (value < 0.0) { - if (value == Double.NEGATIVE_INFINITY) { - return Double.NEGATIVE_INFINITY; - } - value = -value; - // Making sure value is normal. - if (value < DOUBLE_MIN_NORMAL) { - value *= (TWO_POW_52*TWO_POW_26); - // h = * / - h = -2*TWO_POW_N26; - } else { - h = -2.0; - } - } else { - if (!(value < Double.POSITIVE_INFINITY)) { // value is +Infinity, or value is NaN - return value; - } - // Making sure value is normal. - if (value < DOUBLE_MIN_NORMAL) { - if (value == 0.0) { - // cbrt(0.0) = 0.0, cbrt(-0.0) = -0.0 - return value; - } - value *= (TWO_POW_52*TWO_POW_26); - h = 2*TWO_POW_N26; - } else { - h = 2.0; - } - } - - // Normal value is (2^ * ). - // First member cubic root is computed, and multiplied with an approximation - // of the cubic root of the second member, to end up with a good guess of - // the result before using Newton's (or Archimedes's) method. - // To compute the cubic root approximation, we use the formula "cbrt(value) = cbrt(x) * cbrt(value/x)", - // choosing x as close to value as possible but inferior to it, so that cbrt(value/x) is close to 1 - // (we could iterate on this method, using value/x as new value for each iteration, - // but finishing with Newton's method is faster). - - // Shift and cast into an int, which overall is faster than working with a long. - int valueBitsHi = (int)(Double.doubleToRawLongBits(value)>>32); - int valueExponentIndex = (valueBitsHi>>20)+(-MAX_DOUBLE_EXPONENT-MIN_DOUBLE_EXPONENT); - // Getting the first CBRT_LO_BITS bits of the mantissa. - int xIndex = ((valueBitsHi<<12)>>>(32-CBRT_LO_BITS)); - double result = MyTCbrt.cbrtXCbrtHiTab[valueExponentIndex] * MyTCbrt.cbrtXCbrtLoTab[xIndex]; - double slope = MyTCbrt.cbrtSlopeHiTab[valueExponentIndex] * MyTCbrt.cbrtSlopeLoTab[xIndex]; - - // Lowering values to avoid overflows when using Newton's method - // (we will then just have to return twice the result). - // result^3 = value - // (result/2)^3 = value/8 - value *= 0.125; - // No need to divide result here, as division is factorized in result computation tables. - // result *= 0.5; - - // Newton's method, looking for y = x^(1/p): - // y(n) = y(n-1) + (x-y(n-1)^p) * slope(y(n-1)) - // y(n) = y(n-1) + (x-y(n-1)^p) * (1/p)*(x(n-1)^(1/p-1)) - // y(n) = y(n-1) + (x-y(n-1)^p) * (1/p)*(x(n-1)^((1-p)/p)) - // with x(n-1)=y(n-1)^p, i.e.: - // y(n) = y(n-1) + (x-y(n-1)^p) * (1/p)*(y(n-1)^(1-p)) - // - // For p=3: - // y(n) = y(n-1) + (x-y(n-1)^3) * (1/(3*y(n-1)^2)) - - // To save time, we don't recompute the slope between Newton's method steps, - // as initial slope is good enough for a few iterations. - // - // NB: slope = 1/(3*trueResult*trueResult) - // As we have result = trueResult/2 (to avoid overflows), we have: - // slope = 4/(3*result*result) - // = (4/3)*resultInv*resultInv - // with newResultInv = 1/newResult - // = 1/(oldResult+resultDelta) - // = (oldResultInv)*1/(1+resultDelta/oldResult) - // = (oldResultInv)*1/(1+resultDelta*oldResultInv) - // ~= (oldResultInv)*(1-resultDelta*oldResultInv) - // ===> Successive slopes could be computed without division, if needed, - // by computing resultInv (instead of slope right away) and retrieving - // slopes from it. - - result += (value - result * result * result) * slope; - result += (value - result * result * result) * slope; - return h*(result + (value - result * result * result) * slope); - } - - /** - * @return sqrt(x^2+y^2) without intermediate overflow or underflow. - */ - public static double hypot(double x, double y) { - if (USE_JDK_MATH) { - return StrictMath.hypot(x,y); - } - x = Math.abs(x); - y = Math.abs(y); - // Ensuring x <= y. - if (y < x) { - double a = x; - x = y; - y = a; - } else if (!(y >= x)) { // Testing if we have some NaN. - return hypot_NaN(x, y); - } - - if (y-x == y) { - // x too small to subtract from y. - return y; - } else { - double factor; - if (y > HYPOT_MAX_MAG) { - // y is too large: scaling down. - x *= (1/HYPOT_FACTOR); - y *= (1/HYPOT_FACTOR); - factor = HYPOT_FACTOR; - } else if (x < (1/HYPOT_MAX_MAG)) { - // x is too small: scaling up. - x *= HYPOT_FACTOR; - y *= HYPOT_FACTOR; - factor = (1/HYPOT_FACTOR); - } else { - factor = 1.0; - } - return factor * sqrt(x*x+y*y); - } - } - - /** - * @return sqrt(x^2+y^2+z^2) without intermediate overflow or underflow. - */ - public static double hypot(double x, double y, double z) { - if (USE_JDK_MATH) { - // No simple JDK equivalent. - } - x = Math.abs(x); - y = Math.abs(y); - z = Math.abs(z); - /* - * Considering that z magnitude is the most likely to be the smaller, - * hence ensuring z <= y <= x, and not x <= y <= z, for less swaps. - */ - // Ensuring z <= y. - if (z > y) { - // y < z: swapping y and z - double a = z; - z = y; - y = a; - } else if (!(z <= y)) { // Testing if y or z is NaN. - return hypot_NaN(x, y, z); - } - // Ensuring y <= x. - if (z > x) { - // x < z <= y: moving x - double oldZ = z; - z = x; - double oldY = y; - y = oldZ; - x = oldY; - } else if (y > x) { - // z <= x < y: swapping x and y - double a = y; - y = x; - x = a; - } else if (x != x) { // Testing if x is NaN. - return hypot_NaN(x, y, z); - } - - if (x-y == x) { - // y, hence z, too small to subtract from x. - return x; - } else if (y-z == y) { - // z too small to subtract from y, hence x. - double factor; - if (x > HYPOT_MAX_MAG) { - // x is too large: scaling down. - x *= (1/HYPOT_FACTOR); - y *= (1/HYPOT_FACTOR); - factor = HYPOT_FACTOR; - } else if (y < (1/HYPOT_MAX_MAG)) { - // y is too small: scaling up. - x *= HYPOT_FACTOR; - y *= HYPOT_FACTOR; - factor = (1/HYPOT_FACTOR); - } else { - factor = 1.0; - } - return factor * sqrt(x*x+y*y); - } else { - double factor; - if (x > HYPOT_MAX_MAG) { - // x is too large: scaling down. - x *= (1/HYPOT_FACTOR); - y *= (1/HYPOT_FACTOR); - z *= (1/HYPOT_FACTOR); - factor = HYPOT_FACTOR; - } else if (z < (1/HYPOT_MAX_MAG)) { - // z is too small: scaling up. - x *= HYPOT_FACTOR; - y *= HYPOT_FACTOR; - z *= HYPOT_FACTOR; - factor = (1/HYPOT_FACTOR); - } else { - factor = 1.0; - } - // Adding smaller magnitudes together first. - return factor * sqrt(x*x+(y*y+z*z)); - } - } - - /* - * close values - */ - - /** - * @param value A float value. - * @return Floor of value. - */ - public static float floor(float value) { - final int exponent = getExponent(value); - if (exponent < 0) { - // abs(value) < 1. - if (value < 0.0f) { - return -1.0f; - } else { - // 0.0f, or -0.0f if value is -0.0f - return 0.0f * value; - } - } else if (exponent < 23) { - // A bit faster than using casts. - final int bits = Float.floatToRawIntBits(value); - final int anteCommaBits = bits & (0xFF800000>>exponent); - if ((value < 0.0f) && (anteCommaBits != bits)) { - return Float.intBitsToFloat(anteCommaBits) - 1.0f; - } else { - return Float.intBitsToFloat(anteCommaBits); - } - } else { - // +-Infinity, NaN, or a mathematical integer. - return value; - } - } - - /** - * @param value A double value. - * @return Floor of value. - */ - public static double floor(double value) { - if (USE_JDK_MATH) { - return StrictMath.floor(value); - } - if (ANTI_SLOW_CASTS) { - double valueAbs = Math.abs(value); - if (valueAbs <= (double)Integer.MAX_VALUE) { - if (value > 0.0) { - return (double)(int)value; - } else if (value < 0.0) { - double anteCommaDigits = (double)(int)value; - if (value != anteCommaDigits) { - return anteCommaDigits - 1.0; - } else { - return anteCommaDigits; - } - } else { // value is +-0.0 (not NaN due to test against Integer.MAX_VALUE) - return value; - } - } else if (valueAbs < TWO_POW_52) { - // We split the value in two: - // high part, which is a mathematical integer, - // and the rest, for which we can get rid of the - // post comma digits by casting into an int. - double highPart = ((int)(value * TWO_POW_N26)) * TWO_POW_26; - if (value > 0.0) { - return highPart + (double)((int)(value - highPart)); - } else { - double anteCommaDigits = highPart + (double)((int)(value - highPart)); - if (value != anteCommaDigits) { - return anteCommaDigits - 1.0; - } else { - return anteCommaDigits; - } - } - } else { // abs(value) >= 2^52, or value is NaN - return value; - } - } else { - final int exponent = getExponent(value); - if (exponent < 0) { - // abs(value) < 1. - if (value < 0.0) { - return -1.0; - } else { - // 0.0, or -0.0 if value is -0.0 - return 0.0 * value; - } - } else if (exponent < 52) { - // A bit faster than working on bits. - final long matIntPart = (long)value; - final double matIntToValue = value-(double)matIntPart; - if (matIntToValue >= 0.0) { - return (double)matIntPart; - } else { - return (double)(matIntPart - 1); - } - } else { - // +-Infinity, NaN, or a mathematical integer. - return value; - } - } - } - - /** - * @param value A float value. - * @return Ceiling of value. - */ - public static float ceil(float value) { - return -floor(-value); - } - - /** - * @param value A double value. - * @return Ceiling of value. - */ - public static double ceil(double value) { - if (USE_JDK_MATH) { - return StrictMath.ceil(value); - } - return -floor(-value); - } - - /** - * Might have different semantics than StrictMath.round(float), - * see bugs 6430675 and 8010430. - * - * @param value A double value. - * @return Value rounded to nearest int, choosing superior int in case two - * are equally close (i.e. rounding-up). - */ - public static int round(float value) { - /* - * Not delegating to JDK, because we want delegation to provide - * at least as good results, and some supported JDK versions - * have bugged round() methods. - */ - // Algorithm by Dmitry Nadezhin (but replaced an if by a multiply) - // (http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-August/020247.html). - final int bits = Float.floatToRawIntBits(value); - final int biasedExp = ((bits>>23)&0xFF); - // Shift to get rid of bits past comma except first one: will need to - // 1-shift to the right to end up with correct magnitude. - final int shift = (23 - 1 + MAX_FLOAT_EXPONENT) - biasedExp; - if ((shift & -32) == 0) { - int bitsSignum = (((bits >> 31) << 1) + 1); - // shift in [0,31], so unbiased exp in [-9,22]. - int extendedMantissa = (0x00800000 | (bits & 0x007FFFFF)) * bitsSignum; - // If value is positive and first bit past comma is 0, rounding - // to lower integer, else to upper one, which is what "+1" and - // then ">>1" do. - return ((extendedMantissa >> shift) + 1) >> 1; - } else { - // +-Infinity, NaN, or a mathematical integer, or tiny. - if (false && ANTI_SLOW_CASTS) { // not worth it - if (Math.abs(value) >= -(float)Integer.MIN_VALUE) { - // +-Infinity or a mathematical integer (mostly) out of int range. - return (value < 0.0) ? Integer.MIN_VALUE : Integer.MAX_VALUE; - } - // NaN or a mathematical integer (mostly) in int range. - } - return (int)value; - } - } - - /** - * Might have different semantics than StrictMath.round(double), - * see bugs 6430675 and 8010430. - * - * @param value A double value. - * @return Value rounded to nearest long, choosing superior long in case two - * are equally close (i.e. rounding-up). - */ - public static long round(double value) { - /* - * Not delegating to JDK, because we want delegation to provide - * at least as good results, and some supported JDK versions - * have bugged round() methods. - */ - final long bits = Double.doubleToRawLongBits(value); - final int biasedExp = (((int)(bits>>52))&0x7FF); - // Shift to get rid of bits past comma except first one: will need to - // 1-shift to the right to end up with correct magnitude. - final int shift = (52 - 1 + MAX_DOUBLE_EXPONENT) - biasedExp; - if ((shift & -64) == 0) { - long bitsSignum = (((bits >> 63) << 1) + 1); - // shift in [0,63], so unbiased exp in [-12,51]. - long extendedMantissa = (0x0010000000000000L | (bits & 0x000FFFFFFFFFFFFFL)) * bitsSignum; - // If value is positive and first bit past comma is 0, rounding - // to lower integer, else to upper one, which is what "+1" and - // then ">>1" do. - return ((extendedMantissa >> shift) + 1L) >> 1; - } else { - // +-Infinity, NaN, or a mathematical integer, or tiny. - if (ANTI_SLOW_CASTS) { - if (Math.abs(value) >= -(double)Long.MIN_VALUE) { - // +-Infinity or a mathematical integer (mostly) out of long range. - return (value < 0.0) ? Long.MIN_VALUE : Long.MAX_VALUE; - } - // NaN or a mathematical integer (mostly) in long range. - } - return (long)value; - } - } - - /** - * @param value A float value. - * @return Value rounded to nearest int, choosing even int in case two - * are equally close. - */ - public static int roundEven(float value) { - final int sign = signFromBit(value); - value = Math.abs(value); - if (ANTI_SLOW_CASTS) { - if (value < TWO_POW_23_F) { - // Getting rid of post-comma bits. - value = ((value + TWO_POW_23_F) - TWO_POW_23_F); - return sign * (int)value; - } else if (value < (float)Integer.MAX_VALUE) { // "<=" doesn't work, because of float precision - // value is in [-Integer.MAX_VALUE,Integer.MAX_VALUE] - return sign * (int)value; - } - } else { - if (value < TWO_POW_23_F) { - // Getting rid of post-comma bits. - value = ((value + TWO_POW_23_F) - TWO_POW_23_F); - } - } - return (int)(sign * value); - } - - /** - * @param value A double value. - * @return Value rounded to nearest long, choosing even long in case two - * are equally close. - */ - public static long roundEven(double value) { - final int sign = (int)signFromBit(value); - value = Math.abs(value); - if (value < TWO_POW_52) { - // Getting rid of post-comma bits. - value = ((value + TWO_POW_52) - TWO_POW_52); - } - if (ANTI_SLOW_CASTS) { - if (value <= (double)Integer.MAX_VALUE) { - // value is in [-Integer.MAX_VALUE,Integer.MAX_VALUE] - return sign * (int)value; - } - } - return (long)(sign * value); - } - - /** - * @param value A float value. - * @return The float mathematical integer closest to the specified value, - * choosing even one if two are equally close, or respectively - * NaN, +-Infinity or +-0.0f if the value is any of these. - */ - public static float rint(float value) { - final int sign = signFromBit(value); - value = Math.abs(value); - if (value < TWO_POW_23_F) { - // Getting rid of post-comma bits. - value = ((TWO_POW_23_F + value ) - TWO_POW_23_F); - } - // Restoring original sign. - return sign * value; - } - - /** - * @param value A double value. - * @return The double mathematical integer closest to the specified value, - * choosing even one if two are equally close, or respectively - * NaN, +-Infinity or +-0.0 if the value is any of these. - */ - public static double rint(double value) { - if (USE_JDK_MATH) { - return StrictMath.rint(value); - } - final int sign = (int)signFromBit(value); - value = Math.abs(value); - if (value < TWO_POW_52) { - // Getting rid of post-comma bits. - value = ((TWO_POW_52 + value ) - TWO_POW_52); - } - // Restoring original sign. - return sign * value; - } - - /* - * close int values - * - * Never delegating to JDK for these methods, for we should always - * be faster and exact, and JDK doesn't exactly have such methods. - */ - - /** - * @param value A double value. - * @return Floor of value as int, or closest int if floor is out - * of int range, or 0 if value is NaN. - */ - public static int floorToInt(double value) { - int valueInt = (int) value; - if (value < 0.0) { - if (value == (double) valueInt) { - return valueInt; - } else { - if (valueInt == Integer.MIN_VALUE) { - return valueInt; - } else { - return valueInt - 1; - } - } - } else { // >= 0 or NaN. - return valueInt; - } - } - - /** - * @param value A double value. - * @return Ceiling of value as int, or closest int if ceiling is out - * of int range, or 0 if value is NaN. - */ - public static int ceilToInt(double value) { - int valueInt = (int) value; - if (value > 0.0) { - if (value == (double) valueInt) { - return valueInt; - } else { - if (valueInt == Integer.MAX_VALUE) { - return valueInt; - } else { - return valueInt + 1; - } - } - } else { // <= 0 or NaN. - return valueInt; - } - } - - /** - * @param value A double value. - * @return Value rounded to nearest int, choosing superior int in case two - * are equally close (i.e. rounding-up). - */ - public static int roundToInt(double value) { - /* - * We don't gain much by reimplementing rounding, except for - * pathologically large values, which should not be a common case - * when dealing with ints, so we just use round(double). - */ - return NumbersUtils.toInt(round(value)); - } - - /** - * @param value A double value. - * @return Value rounded to nearest int, choosing even int in case two - * are equally close. - */ - public static int roundEvenToInt(double value) { - final int sign = (int)signFromBit(value); - value = Math.abs(value); - /* - * Applying the post-comma bits removal logic even if value is out - * of int range, to avoid a test, for it doesn't mess up the result, - * and we want to optimize for the case of values in int range. - */ - value = ((value + TWO_POW_52) - TWO_POW_52); - return (int)(sign * value); - } - - /* - * ranges - */ - - /** - * @param min A float value. - * @param max A float value. - * @param value A float value. - * @return min if value < min, max if value > max, value otherwise. - */ - public static float toRange(float min, float max, float value) { - return NumbersUtils.toRange(min, max, value); - } - - /** - * @param min A double value. - * @param max A double value. - * @param value A double value. - * @return min if value < min, max if value > max, value otherwise. - */ - public static double toRange(double min, double max, double value) { - return NumbersUtils.toRange(min, max, value); - } - - /* - * binary operators (/,%) - */ - - /** - * Returns dividend - divisor * n, where n is the mathematical integer - * closest to dividend/divisor. - * If dividend/divisor is equally close to surrounding integers, - * we choose n to be the integer of smallest magnitude, which makes - * this treatment differ from StrictMath.IEEEremainder(double,double), - * where n is chosen to be the even integer. - * Note that the choice of n is not done considering the double - * approximation of dividend/divisor, because it could cause - * result to be outside [-|divisor|/2,|divisor|/2] range. - * The practical effect is that if multiple results would be possible, - * we always choose the result that is the closest to (and has the same - * sign as) the dividend. - * Ex. : - * - for (-3.0,2.0), this method returns -1.0, - * whereas StrictMath.IEEEremainder returns 1.0. - * - for (-5.0,2.0), both this method and StrictMath.IEEEremainder return -1.0. - * - * If the remainder is zero, its sign is the same as the sign of the first argument. - * If either argument is NaN, or the first argument is infinite, - * or the second argument is positive zero or negative zero, - * then the result is NaN. - * If the first argument is finite and the second argument is - * infinite, then the result is the same as the first argument. - * - * NB: - * - Modulo operator (%) returns a value in ]-|divisor|,|divisor|[, - * which sign is the same as dividend. - * - As for modulo operator, the sign of the divisor has no effect on the result. - * - On some architecture, % operator has been observed to return NaN - * for some subnormal values of divisor, when dividend exponent is 1023, - * which impacts the correctness of this method. - * - * @param dividend Dividend. - * @param divisor Divisor. - * @return Remainder of dividend/divisor, i.e. a value in [-|divisor|/2,|divisor|/2]. - */ - public static double remainder(double dividend, double divisor) { - if (Double.isInfinite(divisor)) { - if (Double.isInfinite(dividend)) { - return Double.NaN; - } else { - return dividend; - } - } - double value = dividend % divisor; - if (Math.abs(value+value) > Math.abs(divisor)) { - return value + ((value > 0.0) ? -Math.abs(divisor) : Math.abs(divisor)); - } else { - return value; - } - } - - /** - * @param angle Angle in radians. - * @return The same angle, in radians, but in [-PI,PI]. - */ - public static double normalizeMinusPiPi(double angle) { - // Not modifying values in output range. - if ((angle >= -Math.PI) && (angle <= Math.PI)) { - return angle; - } - return remainderTwoPi(angle); - } - - /** - * Not accurate for large values. - * - * @param angle Angle in radians. - * @return The same angle, in radians, but in [-PI,PI]. - */ - public static double normalizeMinusPiPiFast(double angle) { - // Not modifying values in output range. - if ((angle >= -Math.PI) && (angle <= Math.PI)) { - return angle; - } - return remainderTwoPiFast(angle); - } - - /** - * @param angle Angle in radians. - * @return The same angle, in radians, but in [0,2*PI]. - */ - public static double normalizeZeroTwoPi(double angle) { - // Not modifying values in output range. - if ((angle >= 0.0) && (angle <= 2*Math.PI)) { - return angle; - } - angle = remainderTwoPi(angle); - if (angle < 0.0) { - // LO then HI is theoretically better (when starting near 0). - return (angle + TWOPI_LO) + TWOPI_HI; - } else { - return angle; - } - } - - /** - * Not accurate for large values. - * - * @param angle Angle in radians. - * @return The same angle, in radians, but in [0,2*PI]. - */ - public static double normalizeZeroTwoPiFast(double angle) { - // Not modifying values in output range. - if ((angle >= 0.0) && (angle <= 2*Math.PI)) { - return angle; - } - angle = remainderTwoPiFast(angle); - if (angle < 0.0) { - // LO then HI is theoretically better (when starting near 0). - return (angle + TWOPI_LO) + TWOPI_HI; - } else { - return angle; - } - } - - /** - * @param angle Angle in radians. - * @return Angle value modulo PI, in radians, in [-PI/2,PI/2]. - */ - public static double normalizeMinusHalfPiHalfPi(double angle) { - // Not modifying values in output range. - if ((angle >= -Math.PI/2) && (angle <= Math.PI/2)) { - return angle; - } - return remainderPi(angle); - } - - /** - * Not accurate for large values. - * - * @param angle Angle in radians. - * @return Angle value modulo PI, in radians, in [-PI/2,PI/2]. - */ - public static double normalizeMinusHalfPiHalfPiFast(double angle) { - // Not modifying values in output range. - if ((angle >= -Math.PI/2) && (angle <= Math.PI/2)) { - return angle; - } - return remainderPiFast(angle); - } - - /* - * floating points utils - */ - - /** - * @param value A float value. - * @return true if the specified value is NaN or +-Infinity, false otherwise. - */ - public static boolean isNaNOrInfinite(float value) { - return NumbersUtils.isNaNOrInfinite(value); - } - - /** - * @param value A double value. - * @return true if the specified value is NaN or +-Infinity, false otherwise. - */ - public static boolean isNaNOrInfinite(double value) { - return NumbersUtils.isNaNOrInfinite(value); - } - - /** - * @param value A float value. - * @return Value unbiased exponent. - */ - public static int getExponent(float value) { - return ((Float.floatToRawIntBits(value)>>23)&0xFF)-MAX_FLOAT_EXPONENT; - } - - /** - * @param value A double value. - * @return Value unbiased exponent. - */ - public static int getExponent(double value) { - return (((int)(Double.doubleToRawLongBits(value)>>52))&0x7FF)-MAX_DOUBLE_EXPONENT; - } - - /** - * @param value A float value. - * @return -1.0f if the specified value is < 0, 1.0f if it is > 0, - * and the value itself if it is NaN or +-0.0f. - */ - public static float signum(float value) { - if (USE_JDK_MATH) { - return StrictMath.signum(value); - } - if ((value == 0.0f) || (value != value)) { - return value; - } - return (float)signFromBit(value); - } - - /** - * @param value A double value. - * @return -1.0 if the specified value is < 0, 1.0 if it is > 0, - * and the value itself if it is NaN or +-0.0. - */ - public static double signum(double value) { - if (USE_JDK_MATH) { - return StrictMath.signum(value); - } - if ((value == 0.0) || (value != value)) { - return value; - } - if (ANTI_SLOW_CASTS) { - return (double)(int)signFromBit(value); - } else { - return (double)signFromBit(value); - } - } - - /** - * @param value A float value. - * @return -1 if sign bit is 1, 1 if sign bit is 0. - */ - public static int signFromBit(float value) { - return ((Float.floatToRawIntBits(value)>>30)|1); - } - - /** - * @param value A double value. - * @return -1 if sign bit is 1, 1 if sign bit is 0. - */ - public static long signFromBit(double value) { - // Returning a long, to avoid useless cast into int. - return ((Double.doubleToRawLongBits(value)>>62)|1); - } - - /** - * A sign of NaN is interpreted as positive. - * - * @param magnitude A float value. - * @param sign A float value. - * @return A value with the magnitude of the first argument, and the sign - * of the second argument. - */ - public static float copySign(float magnitude, float sign) { - return Float.intBitsToFloat( - (Float.floatToRawIntBits((sign != sign) ? 1.0f : sign) & Integer.MIN_VALUE) - | (Float.floatToRawIntBits(magnitude) & Integer.MAX_VALUE)); - } - - /** - * A sign of NaN is interpreted as positive. - * - * @param magnitude A double value. - * @param sign A double value. - * @return A value with the magnitude of the first argument, and the sign - * of the second argument. - */ - public static double copySign(double magnitude, double sign) { - return Double.longBitsToDouble( - (Double.doubleToRawLongBits((sign != sign) ? 1.0 : sign) & Long.MIN_VALUE) - | (Double.doubleToRawLongBits(magnitude) & Long.MAX_VALUE)); - } - - /** - * The ULP (Unit in the Last Place) is the distance to the next value larger - * in magnitude. - * - * @param value A float value. - * @return The size of an ulp of the specified value, or Float.MIN_VALUE - * if it is +-0.0f, or +Infinity if it is +-Infinity, or NaN - * if it is NaN. - */ - public static float ulp(float value) { - if (USE_JDK_MATH) { - return StrictMath.ulp(value); - } - /* - * Look-up table not really worth it in micro-benchmark, - * so should be worse with cache-misses. - */ - final int exponent = getExponent(value); - if (exponent >= (MIN_FLOAT_NORMAL_EXPONENT+23)) { - if (exponent == MAX_FLOAT_EXPONENT+1) { - // NaN or +-Infinity - return Math.abs(value); - } - // normal: returning 2^(exponent-23) - return Float.intBitsToFloat((exponent+(MAX_FLOAT_EXPONENT-23))<<23); - } else { - if (exponent == MIN_FLOAT_NORMAL_EXPONENT-1) { - // +-0.0f or subnormal - return Float.MIN_VALUE; - } - // subnormal result - return Float.intBitsToFloat(1<<(exponent-MIN_FLOAT_NORMAL_EXPONENT)); - } - } - - /** - * The ULP (Unit in the Last Place) is the distance to the next value larger - * in magnitude. - * - * @param value A double value. - * @return The size of an ulp of the specified value, or Double.MIN_VALUE - * if it is +-0.0, or +Infinity if it is +-Infinity, or NaN - * if it is NaN. - */ - public static double ulp(double value) { - if (USE_JDK_MATH) { - return StrictMath.ulp(value); - } - /* - * Look-up table not really worth it in micro-benchmark, - * so should be worse with cache-misses. - */ - final int exponent = getExponent(value); - if (exponent >= (MIN_DOUBLE_NORMAL_EXPONENT+52)) { - if (exponent == MAX_DOUBLE_EXPONENT+1) { - // NaN or +-Infinity - return Math.abs(value); - } - // normal: returning 2^(exponent-52) - return Double.longBitsToDouble((exponent+(MAX_DOUBLE_EXPONENT-52L))<<52); - } else { - if (exponent == MIN_DOUBLE_NORMAL_EXPONENT-1) { - // +-0.0f or subnormal - return Double.MIN_VALUE; - } - // subnormal result - return Double.longBitsToDouble(1L<<(exponent-MIN_DOUBLE_NORMAL_EXPONENT)); - } - } - - /** - * If both arguments are +-0.0(f), (float)direction is returned. - * - * If both arguments are +Infinity or -Infinity, - * respectively +Infinity or -Infinity is returned. - * - * @param start A float value. - * @param direction A double value. - * @return The float adjacent to start towards direction, considering that - * +(-)Float.MIN_VALUE is adjacent to +(-)0.0f, and that - * +(-)Float.MAX_VALUE is adjacent to +(-)Infinity, - * or NaN if any argument is NaN. - */ - public static float nextAfter(float start, double direction) { - if (direction < start) { - // Going towards -Infinity. - if (start == 0.0f) { - // +-0.0f - return -Float.MIN_VALUE; - } - final int bits = Float.floatToRawIntBits(start); - return Float.intBitsToFloat(bits + ((bits > 0) ? -1 : 1)); - } else if (direction > start) { - // Going towards +Infinity. - // +0.0f to get rid of eventual -0.0f - final int bits = Float.floatToRawIntBits(start + 0.0f); - return Float.intBitsToFloat(bits + (bits >= 0 ? 1 : -1)); - } else if (start == direction) { - return (float)direction; - } else { - // Returning a NaN derived from the input NaN(s). - return start + (float)direction; - } - } - - /** - * If both arguments are +-0.0, direction is returned. - * - * If both arguments are +Infinity or -Infinity, - * respectively +Infinity or -Infinity is returned. - * - * @param start A double value. - * @param direction A double value. - * @return The double adjacent to start towards direction, considering that - * +(-)Double.MIN_VALUE is adjacent to +(-)0.0, and that - * +(-)Double.MAX_VALUE is adjacent to +(-)Infinity, - * or NaN if any argument is NaN. - */ - public static double nextAfter(double start, double direction) { - if (direction < start) { - // Going towards -Infinity. - if (start == 0.0) { - // +-0.0 - return -Double.MIN_VALUE; - } - final long bits = Double.doubleToRawLongBits(start); - return Double.longBitsToDouble(bits + ((bits > 0) ? -1 : 1)); - } else if (direction > start) { - // Going towards +Infinity. - // +0.0 to get rid of eventual -0.0 - final long bits = Double.doubleToRawLongBits(start + 0.0f); - return Double.longBitsToDouble(bits + (bits >= 0 ? 1 : -1)); - } else if (start == direction) { - return direction; - } else { - // Returning a NaN derived from the input NaN(s). - return start + direction; - } - } - - /** - * Semantically equivalent to nextAfter(start,Double.NEGATIVE_INFINITY). - */ - public static float nextDown(float start) { - if (start > Float.NEGATIVE_INFINITY) { - if (start == 0.0f) { - // +-0.0f - return -Float.MIN_VALUE; - } - final int bits = Float.floatToRawIntBits(start); - return Float.intBitsToFloat(bits + ((bits > 0) ? -1 : 1)); - } else if (start == Float.NEGATIVE_INFINITY) { - return Float.NEGATIVE_INFINITY; - } else { - // NaN - return start; - } - } - - /** - * Semantically equivalent to nextAfter(start,Double.NEGATIVE_INFINITY). - */ - public static double nextDown(double start) { - if (start > Double.NEGATIVE_INFINITY) { - if (start == 0.0) { - // +-0.0 - return -Double.MIN_VALUE; - } - final long bits = Double.doubleToRawLongBits(start); - return Double.longBitsToDouble(bits + ((bits > 0) ? -1 : 1)); - } else if (start == Double.NEGATIVE_INFINITY) { - return Double.NEGATIVE_INFINITY; - } else { - // NaN - return start; - } - } - - /** - * Semantically equivalent to nextAfter(start,Double.POSITIVE_INFINITY). - */ - public static float nextUp(float start) { - if (start < Float.POSITIVE_INFINITY) { - // +0.0f to get rid of eventual -0.0f - final int bits = Float.floatToRawIntBits(start + 0.0f); - return Float.intBitsToFloat(bits + (bits >= 0 ? 1 : -1)); - } else if (start == Float.POSITIVE_INFINITY) { - return Float.POSITIVE_INFINITY; - } else { - // NaN - return start; - } - } - - /** - * Semantically equivalent to nextAfter(start,Double.POSITIVE_INFINITY). - */ - public static double nextUp(double start) { - if (start < Double.POSITIVE_INFINITY) { - // +0.0 to get rid of eventual -0.0 - final long bits = Double.doubleToRawLongBits(start + 0.0); - return Double.longBitsToDouble(bits + (bits >= 0 ? 1 : -1)); - } else if (start == Double.POSITIVE_INFINITY) { - return Double.POSITIVE_INFINITY; - } else { - // NaN - return start; - } - } - - /** - * Precision may be lost if the result is subnormal. - * - * @param value A float value. - * @param scaleFactor An int value. - * @return value * 2^scaleFactor, or a value equivalent to the specified - * one if it is NaN, +-Infinity or +-0.0f. - */ - public static float scalb(float value, int scaleFactor) { - // Large enough to imply overflow or underflow for - // a finite non-zero value. - final int MAX_SCALE = 2*MAX_FLOAT_EXPONENT+23+1; - - // Making sure scaling factor is in a reasonable range. - scaleFactor = Math.max(Math.min(scaleFactor, MAX_SCALE), -MAX_SCALE); - - return (float)(((double)value) * twoPowNormal(scaleFactor)); - } - - /** - * Precision may be lost if the result is subnormal. - * - * @param value A double value. - * @param scaleFactor An int value. - * @return value * 2^scaleFactor, or a value equivalent to the specified - * one if it is NaN, +-Infinity or +-0.0. - */ - public static double scalb(double value, int scaleFactor) { - if ((scaleFactor > -MAX_DOUBLE_EXPONENT) && (scaleFactor <= MAX_DOUBLE_EXPONENT)) { - // Quick case (as done in apache FastMath). - return value * twoPowNormal(scaleFactor); - } - - // Large enough to imply overflow or underflow for - // a finite non-zero value. - final int MAX_SCALE = 2*MAX_DOUBLE_EXPONENT+52+1; - - // Making sure scaling factor is in a reasonable range. - final int exponentAdjust; - final int scaleIncrement; - final double exponentDelta; - if (scaleFactor < 0) { - scaleFactor = Math.max(scaleFactor, -MAX_SCALE); - scaleIncrement = -512; - exponentDelta = TWO_POW_N512; - } else { - scaleFactor = Math.min(scaleFactor, MAX_SCALE); - scaleIncrement = 512; - exponentDelta = TWO_POW_512; - } - - // Calculating (scaleFactor % +-512), 512 = 2^9, using - // technique from "Hacker's Delight" section 10-2. - final int t = ((scaleFactor >> (9-1)) >>> (32-9)); - exponentAdjust = ((scaleFactor + t) & (512-1)) - t; - - value *= twoPowNormal(exponentAdjust); - scaleFactor -= exponentAdjust; - - while (scaleFactor != 0) { - value *= exponentDelta; - scaleFactor -= scaleIncrement; - } - - return value; - } - - /* - * Non-redefined StrictMath public values and treatments. - */ - - public static float abs(float a) { - return StrictMath.abs(a); - } - - public static double abs(double a) { - return StrictMath.abs(a); - } - - public static float min(float a, float b) { - return StrictMath.min(a,b); - } - - public static double min(double a, double b) { - return StrictMath.min(a,b); - } - - public static float max(float a, float b) { - return StrictMath.max(a,b); - } - - public static double max(double a, double b) { - return StrictMath.max(a,b); - } - - public static double IEEEremainder(double f1, double f2) { - return StrictMath.IEEEremainder(f1,f2); - } - - public static double random() { - return StrictMath.random(); - } - - //-------------------------------------------------------------------------- - // PRIVATE METHODS - //-------------------------------------------------------------------------- - - /** - * Non-instantiable. - */ - private StrictFastMath() { - } - - /* - * Remainders (accurate). - */ - - /** - * @param angle Angle in radians. - * @return Remainder of (angle % (2*PI)), in [-PI,PI]. - */ - private static double remainderTwoPi(double angle) { - if (USE_JDK_MATH) { - return jdkRemainderTwoPi(angle); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - if (angle <= (4*NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2)) { - double fn = (double)(int)(angle*TWOPI_INV+0.5); - angle = (angle - fn*TWOPI_HI) - fn*TWOPI_LO; - // Ensuring range. - // HI/LO can help a bit, even though we are always far from 0. - if (angle < -Math.PI) { - angle = (angle + TWOPI_HI) + TWOPI_LO; - } else if (angle > Math.PI) { - angle = (angle - TWOPI_HI) - TWOPI_LO; - } - return negateResult ? -angle : angle; - } else if (angle < Double.POSITIVE_INFINITY) { - angle = heavyRemainderTwoPi(angle); - return negateResult ? -angle : angle; - } else { // angle is +Infinity or NaN - return Double.NaN; - } - } - - /** - * @param angle Angle in radians. - * @return Remainder of (angle % PI), in [-PI/2,PI/2]. - */ - private static double remainderPi(double angle) { - if (USE_JDK_MATH) { - return jdkRemainderPi(angle); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - if (angle <= (2*NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2)) { - double fn = (double)(int)(angle*PI_INV+0.5); - angle = (angle - fn*PI_HI) - fn*PI_LO; - // Ensuring range. - // HI/LO can help a bit, even though we are always far from 0. - if (angle < -Math.PI/2) { - angle = (angle + PI_HI) + PI_LO; - } else if (angle > Math.PI/2) { - angle = (angle - PI_HI) - PI_LO; - } - return negateResult ? -angle : angle; - } else if (angle < Double.POSITIVE_INFINITY) { - angle = heavyRemainderPi(angle); - return negateResult ? -angle : angle; - } else { // angle is +Infinity or NaN - return Double.NaN; - } - } - - /** - * @param angle Angle in radians. - * @return Bits of double corresponding to remainder of (angle % (PI/2)), - * in [-PI/4,PI/4], with quadrant encoded in exponent bits. - */ - private static long remainderPiO2(double angle) { - if (USE_JDK_MATH) { - return jdkRemainderPiO2(angle, false); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - if (angle <= NORMALIZE_ANGLE_MAX_MEDIUM_DOUBLE_PIO2) { - int n = (int)(angle*PIO2_INV+0.5); - double fn = (double)n; - angle = (angle - fn*PIO2_HI) - fn*PIO2_LO; - // Ensuring range. - // HI/LO can help a bit, even though we are always far from 0. - if (angle < -Math.PI/4) { - angle = (angle + PIO2_HI) + PIO2_LO; - n--; - } else if (angle > Math.PI/4) { - angle = (angle - PIO2_HI) - PIO2_LO; - n++; - } - if (negateResult) { - angle = -angle; - } - return encodeRemainderAndQuadrant(angle, n&3); - } else if (angle < Double.POSITIVE_INFINITY) { - return heavyRemainderPiO2(angle, negateResult); - } else { // angle is +Infinity or NaN - return encodeRemainderAndQuadrant(Double.NaN, 0); - } - } - - /* - * Remainders (fast). - */ - - /** - * Not accurate for large values. - * - * @param angle Angle in radians. - * @return Remainder of (angle % (2*PI)), in [-PI,PI]. - */ - private static double remainderTwoPiFast(double angle) { - if (USE_JDK_MATH) { - return jdkRemainderTwoPi(angle); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - // - We don't bother with values higher than (2*PI*(2^52)), - // since they are spaced by 2*PI or more from each other. - // - For large values, we don't use % because it might be very slow, - // and we split computation in two, because cast from double to int - // with large numbers might be very slow also. - if (angle <= TWO_POW_26*(2*Math.PI)) { - // ok - } else if (angle <= TWO_POW_52*(2*Math.PI)) { - // Computing remainder of angle modulo TWO_POW_26*(2*PI). - double fn = (double)(int)(angle*(TWOPI_INV/TWO_POW_26)+0.5); - angle = (angle - fn*(TWOPI_HI*TWO_POW_26)) - fn*(TWOPI_LO*TWO_POW_26); - // Here, angle is in [-TWO_POW_26*PI,TWO_POW_26*PI], or so. - if (angle < 0.0) { - angle = -angle; - negateResult = !negateResult; - } - } else if (angle < Double.POSITIVE_INFINITY) { - return 0.0; - } else { // angle is +Infinity or NaN - return Double.NaN; - } - - // Computing remainder of angle modulo 2*PI. - double fn = (double)(int)(angle*TWOPI_INV+0.5); - angle = (angle - fn*TWOPI_HI) - fn*TWOPI_LO; - - // Ensuring range. - // HI/LO can help a bit, even though we are always far from 0. - if (angle < -Math.PI) { - angle = (angle + TWOPI_HI) + TWOPI_LO; - } else if (angle > Math.PI) { - angle = (angle - TWOPI_HI) - TWOPI_LO; - } - return negateResult ? -angle : angle; - } - - /** - * Not accurate for large values. - * - * @param angle Angle in radians. - * @return Remainder of (angle % PI), in [-PI/2,PI/2]. - */ - private static double remainderPiFast(double angle) { - if (USE_JDK_MATH) { - return jdkRemainderPi(angle); - } - boolean negateResult = false; - if (angle < 0.0) { - angle = -angle; - negateResult = true; - } - // - We don't bother with values higher than (PI*(2^52)), - // since they are spaced by PI or more from each other. - // - For large values, we don't use % because it might be very slow, - // and we split computation in two, because cast from double to int - // with large numbers might be very slow also. - if (angle <= TWO_POW_26*Math.PI) { - // ok - } else if (angle <= TWO_POW_52*Math.PI) { - // Computing remainder of angle modulo TWO_POW_26*PI. - double fn = (double)(int)(angle*(PI_INV/TWO_POW_26)+0.5); - angle = (angle - fn*(PI_HI*TWO_POW_26)) - fn*(PI_LO*TWO_POW_26); - // Here, angle is in [-TWO_POW_26*PI/2,TWO_POW_26*PI/2], or so. - if (angle < 0.0) { - angle = -angle; - negateResult = !negateResult; - } - } else if (angle < Double.POSITIVE_INFINITY) { - return 0.0; - } else { // angle is +Infinity or NaN - return Double.NaN; - } - - // Computing remainder of angle modulo PI. - double fn = (double)(int)(angle*PI_INV+0.5); - angle = (angle - fn*PI_HI) - fn*PI_LO; - - // Ensuring range. - // HI/LO can help a bit, even though we are always far from 0. - if (angle < -Math.PI/2) { - angle = (angle + PI_HI) + PI_LO; - } else if (angle > Math.PI/2) { - angle = (angle - PI_HI) - PI_LO; - } - return negateResult ? -angle : angle; - } -} From abb3d9fe5024f31d72354a38efeb3582b9357f46 Mon Sep 17 00:00:00 2001 From: therealansh Date: Thu, 3 Jun 2021 10:17:13 +0530 Subject: [PATCH 382/393] add: Double using StrictMath --- .../kscience/kmath/jafama/KMathJafama.kt | 103 +++++++++--------- 1 file changed, 53 insertions(+), 50 deletions(-) diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt index 2557004e9..9d4341036 100644 --- a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt @@ -4,56 +4,7 @@ import space.kscience.kmath.operations.* import net.jafama.* /** - * Advanced Number-like semifield that implements basic operations. - */ -public interface ExtendedFieldOperations : - FieldOperations, - TrigonometricOperations, - PowerOperations, - ExponentialOperations { - public override fun tan(arg: T): T = sin(arg) / cos(arg) - public override fun tanh(arg: T): T = sinh(arg) / cosh(arg) - - public override fun unaryOperationFunction(operation: String): (arg: T) -> T = when (operation) { - TrigonometricOperations.COS_OPERATION -> ::cos - TrigonometricOperations.SIN_OPERATION -> ::sin - TrigonometricOperations.TAN_OPERATION -> ::tan - TrigonometricOperations.ACOS_OPERATION -> ::acos - TrigonometricOperations.ASIN_OPERATION -> ::asin - TrigonometricOperations.ATAN_OPERATION -> ::atan - PowerOperations.SQRT_OPERATION -> ::sqrt - ExponentialOperations.EXP_OPERATION -> ::exp - ExponentialOperations.LN_OPERATION -> ::ln - ExponentialOperations.COSH_OPERATION -> ::cosh - ExponentialOperations.SINH_OPERATION -> ::sinh - ExponentialOperations.TANH_OPERATION -> ::tanh - ExponentialOperations.ACOSH_OPERATION -> ::acosh - ExponentialOperations.ASINH_OPERATION -> ::asinh - ExponentialOperations.ATANH_OPERATION -> ::atanh - else -> super.unaryOperationFunction(operation) - } -} - -/** - * Advanced Number-like field that implements basic operations. - */ -public interface ExtendedField : ExtendedFieldOperations, Field, NumericAlgebra, ScaleOperations { - public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2.0 - public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2.0 - public override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg)) - public override fun asinh(arg: T): T = ln(sqrt(arg * arg + one) + arg) - public override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one))) - public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2.0 - - public override fun rightSideNumberOperationFunction(operation: String): (left: T, right: Number) -> T = - when (operation) { - PowerOperations.POW_OPERATION -> ::power - else -> super.rightSideNumberOperationFunction(operation) - } -} - -/** - * A field for [Double] without boxing. Does not produce appropriate field element. + * A field for [Double] (using FastMath) without boxing. Does not produce appropriate field element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object JafamaDoubleField : ExtendedField, Norm, ScaleOperations { @@ -101,3 +52,55 @@ public object JafamaDoubleField : ExtendedField, Norm, S public override inline fun Double.times(b: Double): Double = this * b public override inline fun Double.div(b: Double): Double = this / b } + +/** + * A field for [Double] (using StrictMath) without boxing. Does not produce appropriate field element. + */ +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +public object StrictJafamaDoubleField : ExtendedField, Norm, ScaleOperations { + public override inline val zero: Double get() = 0.0 + public override inline val one: Double get() = 1.0 + + public override fun number(value: Number): Double = value.toDouble() + + public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double = + when (operation) { + PowerOperations.POW_OPERATION -> ::power + else -> super.binaryOperationFunction(operation) + } + + public override inline fun add(a: Double, b: Double): Double = a + b + + public override inline fun multiply(a: Double, b: Double): Double = a * b + public override inline fun divide(a: Double, b: Double): Double = a / b + + public override fun scale(a: Double, value: Double): Double = a * value + + public override inline fun sin(arg: Double): Double = StrictFastMath.sin(arg) + public override inline fun cos(arg: Double): Double = StrictFastMath.cos(arg) + public override inline fun tan(arg: Double): Double = StrictFastMath.tan(arg) + public override inline fun acos(arg: Double): Double = StrictFastMath.acos(arg) + public override inline fun asin(arg: Double): Double = StrictFastMath.asin(arg) + public override inline fun atan(arg: Double): Double = StrictFastMath.atan(arg) + + public override inline fun sinh(arg: Double): Double = StrictFastMath.sinh(arg) + public override inline fun cosh(arg: Double): Double = StrictFastMath.cosh(arg) + public override inline fun tanh(arg: Double): Double = StrictFastMath.tanh(arg) + public override inline fun asinh(arg: Double): Double = StrictFastMath.asinh(arg) + public override inline fun acosh(arg: Double): Double = StrictFastMath.acosh(arg) + public override inline fun atanh(arg: Double): Double = StrictFastMath.atanh(arg) + + public override inline fun power(arg: Double, pow: Number): Double = StrictFastMath.pow(arg, pow.toDouble()) + public override inline fun exp(arg: Double): Double = StrictFastMath.exp(arg) + public override inline fun ln(arg: Double): Double = StrictFastMath.log(arg) + + public override inline fun norm(arg: Double): Double = StrictFastMath.abs(arg) + + public override inline fun Double.unaryMinus(): Double = -this + public override inline fun Double.plus(b: Double): Double = this + b + public override inline fun Double.minus(b: Double): Double = this - b + public override inline fun Double.times(b: Double): Double = this * b + public override inline fun Double.div(b: Double): Double = this / b +} + + From 590910ac2dcb0028046442ad0b740328eaecd356 Mon Sep 17 00:00:00 2001 From: therealansh Date: Sat, 5 Jun 2021 11:14:02 +0530 Subject: [PATCH 383/393] add: example and Readme --- README.md | 6 +++++ examples/build.gradle.kts | 2 ++ .../kscience/kmath/jafama/KMathaJafamaDemo.kt | 17 +++++++++++++ kmath-jafama/README.md | 24 +++++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/jafama/KMathaJafamaDemo.kt create mode 100644 kmath-jafama/README.md diff --git a/README.md b/README.md index 7c6f7ea2b..90ab524e2 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,12 @@ One can still use generic algebras though. > **Maturity**: PROTOTYPE
+* ### [kmath-jafama](kmath-jafama) +> +> +> **Maturity**: PROTOTYPE +
+ * ### [kmath-jupyter](kmath-jupyter) > > diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 568bde153..406b8f470 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -44,6 +44,8 @@ dependencies { implementation("org.slf4j:slf4j-simple:1.7.30") // plotting implementation("space.kscience:plotlykt-server:0.4.0") + //jafama + implementation(project(":kmath-jafama")) } kotlin.sourceSets.all { diff --git a/examples/src/main/kotlin/space/kscience/kmath/jafama/KMathaJafamaDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/jafama/KMathaJafamaDemo.kt new file mode 100644 index 000000000..879aab08f --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/jafama/KMathaJafamaDemo.kt @@ -0,0 +1,17 @@ +/* + * 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.jafama + +import net.jafama.FastMath + + +fun main(){ + val a = JafamaDoubleField.number(2.0) + val b = StrictJafamaDoubleField.power(FastMath.E,a) + + println(JafamaDoubleField.add(b,a)) + println(StrictJafamaDoubleField.ln(b)) +} diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md new file mode 100644 index 000000000..fab777bf4 --- /dev/null +++ b/kmath-jafama/README.md @@ -0,0 +1,24 @@ +# Module kmath-jafama + +Jafama based implementation of DoubleField of kmath-operations. + +- JafamaDoubleField : DoubleField implementation using FastMath +- StrictJafamaDoubleField - DoubleField implementation using StrictFastMath + +## Examples + +Different Operations on DoubleField + +```kotlin +package space.kscience.kmath.jafama + +import net.jafama.FastMath + + +fun main(){ + val a = JafamaDoubleField.number(2.0) + val b = StrictJafamaDoubleField.power(FastMath.E,a) + println(JafamaDoubleField.add(b,a)) + println(StrictJafamaDoubleField.ln(b)) +} +``` From 9a9ebc730453735c5b6c0364d9fdbed1e92b3bc3 Mon Sep 17 00:00:00 2001 From: therealansh Date: Tue, 8 Jun 2021 19:19:55 +0530 Subject: [PATCH 384/393] add: benchmarks for Jafama --- benchmarks/build.gradle.kts | 7 +- .../kmath/benchmarks/JafamaBenchmark.kt | 48 ++++++++ .../kscience/kmath/jafama/KMathJafama.kt | 104 +++++++++--------- 3 files changed, 106 insertions(+), 53 deletions(-) create mode 100644 benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 98ffc5a96..182c182d9 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -30,6 +30,7 @@ kotlin { implementation(project(":kmath-stat")) implementation(project(":kmath-dimensions")) implementation(project(":kmath-for-real")) + implementation(project(":kmath-jafama")) implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.0") } } @@ -42,7 +43,6 @@ kotlin { implementation(project(":kmath-kotlingrad")) implementation(project(":kmath-viktor")) implementation("org.nd4j:nd4j-native:1.0.0-beta7") - // uncomment if your system supports AVX2 // val os = System.getProperty("os.name") // @@ -95,6 +95,11 @@ benchmark { commonConfiguration() include("BigIntBenchmark") } + + configurations.register("jafamaDouble") { + commonConfiguration() + include("JafamaBenchmark") + } } // Fix kotlinx-benchmarks bug diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt new file mode 100644 index 000000000..c828de82b --- /dev/null +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt @@ -0,0 +1,48 @@ +/* + * 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.benchmarks + +import kotlinx.benchmark.Blackhole +import org.openjdk.jmh.annotations.Benchmark +import org.openjdk.jmh.annotations.Scope +import org.openjdk.jmh.annotations.State +import space.kscience.kmath.jafama.JafamaDoubleField +import space.kscience.kmath.jafama.StrictJafamaDoubleField +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.invoke + + +@State(Scope.Benchmark) +internal class JafamaBenchmark { + @Benchmark + fun jafamaBench(blackhole: Blackhole) = invokeBenchmarks(jafama, blackhole) + + @Benchmark + fun coreBench(blackhole: Blackhole) = invokeBenchmarks(core,blackhole) + + @Benchmark + fun strictJafamaBench(blackhole: Blackhole) = invokeBenchmarks(strictJafama,blackhole) + + private fun invokeBenchmarks(expr: Double, blackhole: Blackhole) { + blackhole.consume(expr) + } + + private companion object { + private val x: Double = Double.MAX_VALUE + + private val jafama = JafamaDoubleField{ + x * power(x, 1_000_000) * exp(x) / cos(x) + } + + private val core = DoubleField { + x * power(x, 1_000_000) * exp(x) / cos(x) + } + + private val strictJafama = StrictJafamaDoubleField { + x * power(x, 1_000_000) * exp(x) / cos(x) + } + } +} diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt index 9d4341036..f37d8e7b3 100644 --- a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt @@ -8,8 +8,8 @@ import net.jafama.* */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object JafamaDoubleField : ExtendedField, Norm, ScaleOperations { - public override inline val zero: Double get() = 0.0 - public override inline val one: Double get() = 1.0 + public override val zero: Double get() = 0.0 + public override val one: Double get() = 1.0 public override fun number(value: Number): Double = value.toDouble() @@ -19,38 +19,38 @@ public object JafamaDoubleField : ExtendedField, Norm, S else -> super.binaryOperationFunction(operation) } - public override inline fun add(a: Double, b: Double): Double = a + b + public override fun add(a: Double, b: Double): Double = a + b - public override inline fun multiply(a: Double, b: Double): Double = a * b - public override inline fun divide(a: Double, b: Double): Double = a / b + public override fun multiply(a: Double, b: Double): Double = a * b + public override fun divide(a: Double, b: Double): Double = a / b public override fun scale(a: Double, value: Double): Double = a * value - public override inline fun sin(arg: Double): Double = FastMath.sin(arg) - public override inline fun cos(arg: Double): Double = FastMath.cos(arg) - public override inline fun tan(arg: Double): Double = FastMath.tan(arg) - public override inline fun acos(arg: Double): Double = FastMath.acos(arg) - public override inline fun asin(arg: Double): Double = FastMath.asin(arg) - public override inline fun atan(arg: Double): Double = FastMath.atan(arg) + public override fun sin(arg: Double): Double = FastMath.sin(arg) + public override fun cos(arg: Double): Double = FastMath.cos(arg) + public override fun tan(arg: Double): Double = FastMath.tan(arg) + public override fun acos(arg: Double): Double = FastMath.acos(arg) + public override fun asin(arg: Double): Double = FastMath.asin(arg) + public override fun atan(arg: Double): Double = FastMath.atan(arg) - public override inline fun sinh(arg: Double): Double = FastMath.sinh(arg) - public override inline fun cosh(arg: Double): Double = FastMath.cosh(arg) - public override inline fun tanh(arg: Double): Double = FastMath.tanh(arg) - public override inline fun asinh(arg: Double): Double = FastMath.asinh(arg) - public override inline fun acosh(arg: Double): Double = FastMath.acosh(arg) - public override inline fun atanh(arg: Double): Double = FastMath.atanh(arg) + public override fun sinh(arg: Double): Double = FastMath.sinh(arg) + public override fun cosh(arg: Double): Double = FastMath.cosh(arg) + public override fun tanh(arg: Double): Double = FastMath.tanh(arg) + public override fun asinh(arg: Double): Double = FastMath.asinh(arg) + public override fun acosh(arg: Double): Double = FastMath.acosh(arg) + public override fun atanh(arg: Double): Double = FastMath.atanh(arg) - public override inline fun power(arg: Double, pow: Number): Double = FastMath.pow(arg, pow.toDouble()) - public override inline fun exp(arg: Double): Double = FastMath.exp(arg) - public override inline fun ln(arg: Double): Double = FastMath.log(arg) + public override fun power(arg: Double, pow: Number): Double = FastMath.pow(arg, pow.toDouble()) + public override fun exp(arg: Double): Double = FastMath.exp(arg) + public override fun ln(arg: Double): Double = FastMath.log(arg) - public override inline fun norm(arg: Double): Double = FastMath.abs(arg) + public override fun norm(arg: Double): Double = FastMath.abs(arg) - public override inline fun Double.unaryMinus(): Double = -this - public override inline fun Double.plus(b: Double): Double = this + b - public override inline fun Double.minus(b: Double): Double = this - b - public override inline fun Double.times(b: Double): Double = this * b - public override inline fun Double.div(b: Double): Double = this / b + public override fun Double.unaryMinus(): Double = -this + public override fun Double.plus(b: Double): Double = this + b + public override fun Double.minus(b: Double): Double = this - b + public override fun Double.times(b: Double): Double = this * b + public override fun Double.div(b: Double): Double = this / b } /** @@ -58,8 +58,8 @@ public object JafamaDoubleField : ExtendedField, Norm, S */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object StrictJafamaDoubleField : ExtendedField, Norm, ScaleOperations { - public override inline val zero: Double get() = 0.0 - public override inline val one: Double get() = 1.0 + public override val zero: Double get() = 0.0 + public override val one: Double get() = 1.0 public override fun number(value: Number): Double = value.toDouble() @@ -69,38 +69,38 @@ public object StrictJafamaDoubleField : ExtendedField, Norm super.binaryOperationFunction(operation) } - public override inline fun add(a: Double, b: Double): Double = a + b + public override fun add(a: Double, b: Double): Double = a + b - public override inline fun multiply(a: Double, b: Double): Double = a * b - public override inline fun divide(a: Double, b: Double): Double = a / b + public override fun multiply(a: Double, b: Double): Double = a * b + public override fun divide(a: Double, b: Double): Double = a / b public override fun scale(a: Double, value: Double): Double = a * value - public override inline fun sin(arg: Double): Double = StrictFastMath.sin(arg) - public override inline fun cos(arg: Double): Double = StrictFastMath.cos(arg) - public override inline fun tan(arg: Double): Double = StrictFastMath.tan(arg) - public override inline fun acos(arg: Double): Double = StrictFastMath.acos(arg) - public override inline fun asin(arg: Double): Double = StrictFastMath.asin(arg) - public override inline fun atan(arg: Double): Double = StrictFastMath.atan(arg) + public override fun sin(arg: Double): Double = StrictFastMath.sin(arg) + public override fun cos(arg: Double): Double = StrictFastMath.cos(arg) + public override fun tan(arg: Double): Double = StrictFastMath.tan(arg) + public override fun acos(arg: Double): Double = StrictFastMath.acos(arg) + public override fun asin(arg: Double): Double = StrictFastMath.asin(arg) + public override fun atan(arg: Double): Double = StrictFastMath.atan(arg) - public override inline fun sinh(arg: Double): Double = StrictFastMath.sinh(arg) - public override inline fun cosh(arg: Double): Double = StrictFastMath.cosh(arg) - public override inline fun tanh(arg: Double): Double = StrictFastMath.tanh(arg) - public override inline fun asinh(arg: Double): Double = StrictFastMath.asinh(arg) - public override inline fun acosh(arg: Double): Double = StrictFastMath.acosh(arg) - public override inline fun atanh(arg: Double): Double = StrictFastMath.atanh(arg) + public override fun sinh(arg: Double): Double = StrictFastMath.sinh(arg) + public override fun cosh(arg: Double): Double = StrictFastMath.cosh(arg) + public override fun tanh(arg: Double): Double = StrictFastMath.tanh(arg) + public override fun asinh(arg: Double): Double = StrictFastMath.asinh(arg) + public override fun acosh(arg: Double): Double = StrictFastMath.acosh(arg) + public override fun atanh(arg: Double): Double = StrictFastMath.atanh(arg) - public override inline fun power(arg: Double, pow: Number): Double = StrictFastMath.pow(arg, pow.toDouble()) - public override inline fun exp(arg: Double): Double = StrictFastMath.exp(arg) - public override inline fun ln(arg: Double): Double = StrictFastMath.log(arg) + public override fun power(arg: Double, pow: Number): Double = StrictFastMath.pow(arg, pow.toDouble()) + public override fun exp(arg: Double): Double = StrictFastMath.exp(arg) + public override fun ln(arg: Double): Double = StrictFastMath.log(arg) - public override inline fun norm(arg: Double): Double = StrictFastMath.abs(arg) + public override fun norm(arg: Double): Double = StrictFastMath.abs(arg) - public override inline fun Double.unaryMinus(): Double = -this - public override inline fun Double.plus(b: Double): Double = this + b - public override inline fun Double.minus(b: Double): Double = this - b - public override inline fun Double.times(b: Double): Double = this * b - public override inline fun Double.div(b: Double): Double = this / b + public override fun Double.unaryMinus(): Double = -this + public override fun Double.plus(b: Double): Double = this + b + public override fun Double.minus(b: Double): Double = this - b + public override fun Double.times(b: Double): Double = this * b + public override fun Double.div(b: Double): Double = this / b } From b99d0b96d82289a738326b7b4a71df6064734519 Mon Sep 17 00:00:00 2001 From: therealansh Date: Tue, 8 Jun 2021 19:28:34 +0530 Subject: [PATCH 385/393] add:benchmarks to readme --- kmath-jafama/README.md | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md index fab777bf4..bc5655a1e 100644 --- a/kmath-jafama/README.md +++ b/kmath-jafama/README.md @@ -22,3 +22,47 @@ fun main(){ println(StrictJafamaDoubleField.ln(b)) } ``` + +## Benchmarks +Comparing Operations on DoubleField and JafamaDoubleField +```bash +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench + +Warm-up 1: 242556635.528 ops/s +Iteration 1: 236249893.335 ops/s +Iteration 2: 294526940.968 ops/s +Iteration 3: 295973752.533 ops/s +Iteration 4: 296467676.763 ops/s +Iteration 5: 295929441.421 ops/s + +283829541.004 ±(99.9%) 102456604.440 ops/s [Average] + (min, avg, max) = (236249893.335, 283829541.004, 296467676.763), stdev = 26607654.808 + CI (99.9%): [181372936.564, 386286145.444] (assumes normal distribution) + +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench + +Warm-up 1: 234737640.196 ops/s +Iteration 1: 231689614.905 ops/s +Iteration 2: 296629612.909 ops/s +Iteration 3: 297456237.453 ops/s +Iteration 4: 296754794.513 ops/s +Iteration 5: 293722557.848 ops/s + +283250563.526 ±(99.9%) 111125582.233 ops/s [Average] + (min, avg, max) = (231689614.905, 283250563.526, 297456237.453), stdev = 28858960.811 + CI (99.9%): [172124981.293, 394376145.759] (assumes normal distribution) + +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench + +Warm-up 1: 234895701.589 ops/s +Iteration 1: 236061284.195 ops/s +Iteration 2: 296894799.416 ops/s +Iteration 3: 286852020.677 ops/s +Iteration 4: 284021863.614 ops/s +Iteration 5: 284404358.656 ops/s + +277646865.312 ±(99.9%) 91748868.927 ops/s [Average] + (min, avg, max) = (236061284.195, 277646865.312, 296894799.416), stdev = 23826889.899 + CI (99.9%): [185897996.385, 369395734.239] (assumes normal distribution) + +``` From 03be37bb4f6843a8fb08b3c44256df4f6bbdb15f Mon Sep 17 00:00:00 2001 From: therealansh Date: Sat, 12 Jun 2021 10:00:36 +0530 Subject: [PATCH 386/393] add: kotlin math benchmarks --- .../kmath/benchmarks/JafamaBenchmark.kt | 8 +++ kmath-jafama/README.md | 68 +++++++++++-------- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt index c828de82b..e998054fb 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt @@ -13,6 +13,9 @@ import space.kscience.kmath.jafama.JafamaDoubleField import space.kscience.kmath.jafama.StrictJafamaDoubleField import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke +import kotlin.math.cos +import kotlin.math.exp +import kotlin.math.pow @State(Scope.Benchmark) @@ -26,6 +29,9 @@ internal class JafamaBenchmark { @Benchmark fun strictJafamaBench(blackhole: Blackhole) = invokeBenchmarks(strictJafama,blackhole) + @Benchmark + fun kotlinMathBench(blackhole: Blackhole) = invokeBenchmarks(kotlinMath, blackhole) + private fun invokeBenchmarks(expr: Double, blackhole: Blackhole) { blackhole.consume(expr) } @@ -37,6 +43,8 @@ internal class JafamaBenchmark { x * power(x, 1_000_000) * exp(x) / cos(x) } + private val kotlinMath = x * x.pow(1_000_000) * exp(x) / cos(x) + private val core = DoubleField { x * power(x, 1_000_000) * exp(x) / cos(x) } diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md index bc5655a1e..d170f6591 100644 --- a/kmath-jafama/README.md +++ b/kmath-jafama/README.md @@ -28,41 +28,53 @@ Comparing Operations on DoubleField and JafamaDoubleField ```bash jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench -Warm-up 1: 242556635.528 ops/s -Iteration 1: 236249893.335 ops/s -Iteration 2: 294526940.968 ops/s -Iteration 3: 295973752.533 ops/s -Iteration 4: 296467676.763 ops/s -Iteration 5: 295929441.421 ops/s +Warm-up 1: 384414358.081 ops/s +Iteration 1: 374827571.951 ops/s +Iteration 2: 479335182.332 ops/s +Iteration 3: 475483069.577 ops/s +Iteration 4: 478235949.414 ops/s +Iteration 5: 472256385.114 ops/s -283829541.004 ±(99.9%) 102456604.440 ops/s [Average] - (min, avg, max) = (236249893.335, 283829541.004, 296467676.763), stdev = 26607654.808 - CI (99.9%): [181372936.564, 386286145.444] (assumes normal distribution) +456027631.678 ±(99.9%) 175106815.384 ops/s [Average] + (min, avg, max) = (374827571.951, 456027631.678, 479335182.332), stdev = 45474683.880 + CI (99.9%): [280920816.294, 631134447.061] (assumes normal distribution) jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench -Warm-up 1: 234737640.196 ops/s -Iteration 1: 231689614.905 ops/s -Iteration 2: 296629612.909 ops/s -Iteration 3: 297456237.453 ops/s -Iteration 4: 296754794.513 ops/s -Iteration 5: 293722557.848 ops/s +Warm-up 1: 359418665.041 ops/s +Iteration 1: 335704885.798 ops/s +Iteration 2: 427684801.542 ops/s +Iteration 3: 452193034.265 ops/s +Iteration 4: 433855064.931 ops/s +Iteration 5: 453863386.566 ops/s -283250563.526 ±(99.9%) 111125582.233 ops/s [Average] - (min, avg, max) = (231689614.905, 283250563.526, 297456237.453), stdev = 28858960.811 - CI (99.9%): [172124981.293, 394376145.759] (assumes normal distribution) +420660234.620 ±(99.9%) 188028426.875 ops/s [Average] + (min, avg, max) = (335704885.798, 420660234.620, 453863386.566), stdev = 48830385.349 + CI (99.9%): [232631807.746, 608688661.495] (assumes normal distribution) + +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.kotlinMathBench + +Warm-up 1: 371570418.113 ops/s +Iteration 1: 379281146.127 ops/s +Iteration 2: 465234403.109 ops/s +Iteration 3: 470621634.240 ops/s +Iteration 4: 467074553.006 ops/s +Iteration 5: 466424840.144 ops/s + +449727315.325 ±(99.9%) 151837475.500 ops/s [Average] + (min, avg, max) = (379281146.127, 449727315.325, 470621634.240), stdev = 39431710.207 + CI (99.9%): [297889839.825, 601564790.825] (assumes normal distribution) jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench -Warm-up 1: 234895701.589 ops/s -Iteration 1: 236061284.195 ops/s -Iteration 2: 296894799.416 ops/s -Iteration 3: 286852020.677 ops/s -Iteration 4: 284021863.614 ops/s -Iteration 5: 284404358.656 ops/s - -277646865.312 ±(99.9%) 91748868.927 ops/s [Average] - (min, avg, max) = (236061284.195, 277646865.312, 296894799.416), stdev = 23826889.899 - CI (99.9%): [185897996.385, 369395734.239] (assumes normal distribution) +Warm-up 1: 371241281.065 ops/s +Iteration 1: 374490259.387 ops/s +Iteration 2: 464995837.424 ops/s +Iteration 3: 469788706.385 ops/s +Iteration 4: 469528470.682 ops/s +Iteration 5: 456727921.978 ops/s +447106239.171 ±(99.9%) 157629035.980 ops/s [Average] + (min, avg, max) = (374490259.387, 447106239.171, 469788706.385), stdev = 40935760.071 + CI (99.9%): [289477203.192, 604735275.151] (assumes normal distribution) ``` From 4d6428a3082c4c1b775cc1e70e35b42032e5ad49 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Mon, 14 Jun 2021 21:51:06 +0700 Subject: [PATCH 387/393] Update Jafama module documentation with some minor code amendments --- README.md | 8 +- benchmarks/build.gradle.kts | 1 + .../kmath/benchmarks/JafamaBenchmark.kt | 45 ++--- kmath-ast/build.gradle.kts | 7 +- .../kmath/ast/TestCompilerOperations.kt | 1 - .../kscience/kmath/operations/numbers.kt | 6 +- kmath-functions/build.gradle.kts | 5 +- kmath-jafama/README.md | 178 ++++++++++++------ kmath-jafama/build.gradle.kts | 7 + kmath-jafama/docs/README-TEMPLATE.md | 118 ++++++++++++ .../kscience/kmath/jafama/KMathJafama.kt | 124 ++++++------ 11 files changed, 341 insertions(+), 159 deletions(-) create mode 100644 kmath-jafama/docs/README-TEMPLATE.md diff --git a/README.md b/README.md index 90ab524e2..015988cd3 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,7 @@ One can still use generic algebras though.
* ### [kmath-functions](kmath-functions) -> Functions, integration and interpolation +> > > **Maturity**: EXPERIMENTAL > @@ -201,9 +201,13 @@ One can still use generic algebras though.
* ### [kmath-jafama](kmath-jafama) -> +> > > **Maturity**: PROTOTYPE +> +> **Features:** +> - [jafama-double](kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/) : Double ExtendedField implementations based on Jafama +
* ### [kmath-jupyter](kmath-jupyter) diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 182c182d9..f171437d3 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -12,6 +12,7 @@ repositories { maven("https://repo.kotlin.link") maven("https://clojars.org/repo") maven("https://jitpack.io") + maven("http://logicrunch.research.it.uu.se/maven") { isAllowInsecureProtocol = true } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt index e998054fb..260eea2b6 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt @@ -13,44 +13,27 @@ import space.kscience.kmath.jafama.JafamaDoubleField import space.kscience.kmath.jafama.StrictJafamaDoubleField import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke -import kotlin.math.cos -import kotlin.math.exp -import kotlin.math.pow - +import kotlin.random.Random @State(Scope.Benchmark) internal class JafamaBenchmark { @Benchmark - fun jafamaBench(blackhole: Blackhole) = invokeBenchmarks(jafama, blackhole) - - @Benchmark - fun coreBench(blackhole: Blackhole) = invokeBenchmarks(core,blackhole) - - @Benchmark - fun strictJafamaBench(blackhole: Blackhole) = invokeBenchmarks(strictJafama,blackhole) - - @Benchmark - fun kotlinMathBench(blackhole: Blackhole) = invokeBenchmarks(kotlinMath, blackhole) - - private fun invokeBenchmarks(expr: Double, blackhole: Blackhole) { - blackhole.consume(expr) + fun jafamaBench(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x -> + JafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) } } - private companion object { - private val x: Double = Double.MAX_VALUE + @Benchmark + fun coreBench(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x -> + DoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) } + } - private val jafama = JafamaDoubleField{ - x * power(x, 1_000_000) * exp(x) / cos(x) - } + @Benchmark + fun strictJafamaBench(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x -> + StrictJafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) } + } - private val kotlinMath = x * x.pow(1_000_000) * exp(x) / cos(x) - - private val core = DoubleField { - x * power(x, 1_000_000) * exp(x) / cos(x) - } - - private val strictJafama = StrictJafamaDoubleField { - x * power(x, 1_000_000) * exp(x) / cos(x) - } + private inline fun invokeBenchmarks(blackhole: Blackhole, expr: (Double) -> Double) { + val rng = Random(0) + repeat(1000000) { blackhole.consume(expr(rng.nextDouble())) } } } diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 508374d82..89647c9e9 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -37,10 +37,9 @@ kotlin.sourceSets { jsMain { dependencies { - implementation(npm("astring", "1.7.4")) - implementation(npm("binaryen", "100.0")) - implementation(npm("js-base64", "3.6.0")) - implementation(npm("webassembly", "0.11.0")) + implementation(npm("astring", "1.7.5")) + implementation(npm("binaryen", "101.0.0")) + implementation(npm("js-base64", "3.6.1")) } } diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt index f869efd62..929d17775 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt @@ -9,7 +9,6 @@ import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.Symbol.Companion.x import space.kscience.kmath.expressions.invoke import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt index 0d6d9e98d..36c13d6ec 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt @@ -64,7 +64,7 @@ public object DoubleField : ExtendedField, Norm, ScaleOp public override inline val zero: Double get() = 0.0 public override inline val one: Double get() = 1.0 - public override fun number(value: Number): Double = value.toDouble() + public override inline fun number(value: Number): Double = value.toDouble() public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double = when (operation) { @@ -77,7 +77,7 @@ public object DoubleField : ExtendedField, Norm, ScaleOp public override inline fun multiply(a: Double, b: Double): Double = a * b public override inline fun divide(a: Double, b: Double): Double = a / b - public override fun scale(a: Double, value: Double): Double = a * value + public override inline fun scale(a: Double, value: Double): Double = a * value public override inline fun sin(arg: Double): Double = kotlin.math.sin(arg) public override inline fun cos(arg: Double): Double = kotlin.math.cos(arg) @@ -93,6 +93,7 @@ public object DoubleField : ExtendedField, Norm, ScaleOp public override inline fun acosh(arg: Double): Double = kotlin.math.acosh(arg) public override inline fun atanh(arg: Double): Double = kotlin.math.atanh(arg) + public override inline fun sqrt(arg: Double): Double = kotlin.math.sqrt(arg) public override inline fun power(arg: Double, pow: Number): Double = arg.kpow(pow.toDouble()) public override inline fun exp(arg: Double): Double = kotlin.math.exp(arg) public override inline fun ln(arg: Double): Double = kotlin.math.ln(arg) @@ -143,6 +144,7 @@ public object FloatField : ExtendedField, Norm { public override inline fun acosh(arg: Float): Float = kotlin.math.acosh(arg) public override inline fun atanh(arg: Float): Float = kotlin.math.atanh(arg) + public override inline fun sqrt(arg: Float): Float = kotlin.math.sqrt(arg) public override inline fun power(arg: Float, pow: Number): Float = arg.kpow(pow.toFloat()) public override inline fun exp(arg: Float): Float = kotlin.math.exp(arg) public override inline fun ln(arg: Float): Float = kotlin.math.ln(arg) diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 622b8f8da..f77df3833 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -3,6 +3,8 @@ plugins { id("ru.mipt.npm.gradle.common") } +description = "Functions, integration and interpolation" + kotlin.sourceSets.commonMain { dependencies { api(project(":kmath-core")) @@ -10,7 +12,6 @@ kotlin.sourceSets.commonMain { } readme { - description = "Functions, integration and interpolation" maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) @@ -29,4 +30,4 @@ readme { feature("integration") { "Univariate and multivariate quadratures" } -} \ No newline at end of file +} diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md index d170f6591..9b439c5c2 100644 --- a/kmath-jafama/README.md +++ b/kmath-jafama/README.md @@ -1,80 +1,144 @@ # Module kmath-jafama -Jafama based implementation of DoubleField of kmath-operations. +Integration with [Jafama](https://github.com/jeffhain/jafama). -- JafamaDoubleField : DoubleField implementation using FastMath -- StrictJafamaDoubleField - DoubleField implementation using StrictFastMath + - [jafama-double](src/main/kotlin/space/kscience/kmath/jafama/) : Double ExtendedField implementations based on Jafama -## Examples -Different Operations on DoubleField +## Artifact: +The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.0-dev-13`. + +**Gradle:** +```gradle +repositories { + maven { url 'https://repo.kotlin.link' } + mavenCentral() +} + +dependencies { + implementation 'space.kscience:kmath-jafama:0.3.0-dev-13' +} +``` +**Gradle Kotlin DSL:** ```kotlin -package space.kscience.kmath.jafama +repositories { + maven("https://repo.kotlin.link") + mavenCentral() +} -import net.jafama.FastMath - - -fun main(){ - val a = JafamaDoubleField.number(2.0) - val b = StrictJafamaDoubleField.power(FastMath.E,a) - println(JafamaDoubleField.add(b,a)) - println(StrictJafamaDoubleField.ln(b)) +dependencies { + implementation("space.kscience:kmath-jafama:0.3.0-dev-13") } ``` -## Benchmarks -Comparing Operations on DoubleField and JafamaDoubleField -```bash +## Example usage + +All the `DoubleField` uses can be replaced with `JafamaDoubleField` or `StrictJafamaDoubleField`. + +```kotlin +import space.kscience.kmath.jafama.* +import space.kscience.kmath.operations.* + +fun main() { + val a = 2.0 + val b = StrictJafamaDoubleField { exp(a) } + println(JafamaDoubleField { b + a }) + println(StrictJafamaDoubleField { ln(b) }) +} +``` + +## Performance + +According to benchmarking data, on Hotspot Jafama functions are 20% faster than JDK math. On GraalVM, they are slower. + +
+Raw data: + +**Hotspot** + +``` jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench -Warm-up 1: 384414358.081 ops/s -Iteration 1: 374827571.951 ops/s -Iteration 2: 479335182.332 ops/s -Iteration 3: 475483069.577 ops/s -Iteration 4: 478235949.414 ops/s -Iteration 5: 472256385.114 ops/s +Warm-up 1: 11.447 ops/s +Iteration 1: 13.354 ops/s +Iteration 2: 14.237 ops/s +Iteration 3: 14.708 ops/s +Iteration 4: 14.629 ops/s +Iteration 5: 14.692 ops/s -456027631.678 ±(99.9%) 175106815.384 ops/s [Average] - (min, avg, max) = (374827571.951, 456027631.678, 479335182.332), stdev = 45474683.880 - CI (99.9%): [280920816.294, 631134447.061] (assumes normal distribution) +14.324 ±(99.9%) 2.217 ops/s [Average] + (min, avg, max) = (13.354, 14.324, 14.708), stdev = 0.576 + CI (99.9%): [12.107, 16.541] (assumes normal distribution) jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench -Warm-up 1: 359418665.041 ops/s -Iteration 1: 335704885.798 ops/s -Iteration 2: 427684801.542 ops/s -Iteration 3: 452193034.265 ops/s -Iteration 4: 433855064.931 ops/s -Iteration 5: 453863386.566 ops/s +Warm-up 1: 15.628 ops/s +Iteration 1: 15.991 ops/s +Iteration 2: 16.633 ops/s +Iteration 3: 16.583 ops/s +Iteration 4: 16.716 ops/s +Iteration 5: 16.762 ops/s -420660234.620 ±(99.9%) 188028426.875 ops/s [Average] - (min, avg, max) = (335704885.798, 420660234.620, 453863386.566), stdev = 48830385.349 - CI (99.9%): [232631807.746, 608688661.495] (assumes normal distribution) - -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.kotlinMathBench - -Warm-up 1: 371570418.113 ops/s -Iteration 1: 379281146.127 ops/s -Iteration 2: 465234403.109 ops/s -Iteration 3: 470621634.240 ops/s -Iteration 4: 467074553.006 ops/s -Iteration 5: 466424840.144 ops/s - -449727315.325 ±(99.9%) 151837475.500 ops/s [Average] - (min, avg, max) = (379281146.127, 449727315.325, 470621634.240), stdev = 39431710.207 - CI (99.9%): [297889839.825, 601564790.825] (assumes normal distribution) +16.537 ±(99.9%) 1.205 ops/s [Average] + (min, avg, max) = (15.991, 16.537, 16.762), stdev = 0.313 + CI (99.9%): [15.332, 17.743] (assumes normal distribution) jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench -Warm-up 1: 371241281.065 ops/s -Iteration 1: 374490259.387 ops/s -Iteration 2: 464995837.424 ops/s -Iteration 3: 469788706.385 ops/s -Iteration 4: 469528470.682 ops/s -Iteration 5: 456727921.978 ops/s +Warm-up 1: 13.378 ops/s +Iteration 1: 15.049 ops/s +Iteration 2: 14.468 ops/s +Iteration 3: 14.469 ops/s +Iteration 4: 14.753 ops/s +Iteration 5: 14.958 ops/s -447106239.171 ±(99.9%) 157629035.980 ops/s [Average] - (min, avg, max) = (374490259.387, 447106239.171, 469788706.385), stdev = 40935760.071 - CI (99.9%): [289477203.192, 604735275.151] (assumes normal distribution) +14.739 ±(99.9%) 1.038 ops/s [Average] + (min, avg, max) = (14.468, 14.739, 15.049), stdev = 0.269 + CI (99.9%): [13.701, 15.777] (assumes normal distribution) ``` + +**GraalVM** + +``` +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench + +Warm-up 1: 14.357 ops/s +Iteration 1: 14.768 ops/s +Iteration 2: 14.922 ops/s +Iteration 3: 14.966 ops/s +Iteration 4: 14.805 ops/s +Iteration 5: 14.520 ops/s + +14.796 ±(99.9%) 0.671 ops/s [Average] + (min, avg, max) = (14.520, 14.796, 14.966), stdev = 0.174 + CI (99.9%): [14.125, 15.468] (assumes normal distribution) + +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench + +Warm-up 1: 11.592 ops/s +Iteration 1: 12.174 ops/s +Iteration 2: 11.734 ops/s +Iteration 3: 11.939 ops/s +Iteration 4: 12.026 ops/s +Iteration 5: 12.221 ops/s + +12.019 ±(99.9%) 0.752 ops/s [Average] + (min, avg, max) = (11.734, 12.019, 12.221), stdev = 0.195 + CI (99.9%): [11.267, 12.771] (assumes normal distribution) + +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench + +Warm-up 1: 12.097 ops/s +Iteration 1: 13.072 ops/s +Iteration 2: 13.112 ops/s +Iteration 3: 13.103 ops/s +Iteration 4: 12.950 ops/s +Iteration 5: 13.011 ops/s + +13.049 ±(99.9%) 0.263 ops/s [Average] + (min, avg, max) = (12.950, 13.049, 13.112), stdev = 0.068 + CI (99.9%): [12.787, 13.312] (assumes normal distribution) +``` + +
diff --git a/kmath-jafama/build.gradle.kts b/kmath-jafama/build.gradle.kts index f31f2602f..9cf328d0b 100644 --- a/kmath-jafama/build.gradle.kts +++ b/kmath-jafama/build.gradle.kts @@ -2,6 +2,8 @@ plugins { id("ru.mipt.npm.gradle.jvm") } +description = "Jafama integration module" + dependencies { api(project(":kmath-core")) api("net.jafama:jafama:2.3.2") @@ -13,6 +15,11 @@ repositories { readme { maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + + feature("jafama-double", "src/main/kotlin/space/kscience/kmath/jafama/") { + "Double ExtendedField implementations based on Jafama" + } } kotlin.sourceSets.all { diff --git a/kmath-jafama/docs/README-TEMPLATE.md b/kmath-jafama/docs/README-TEMPLATE.md new file mode 100644 index 000000000..fa58f7697 --- /dev/null +++ b/kmath-jafama/docs/README-TEMPLATE.md @@ -0,0 +1,118 @@ +# Module kmath-jafama + +Integration with [Jafama](https://github.com/jeffhain/jafama). + +${features} + +${artifact} + +## Example usage + +All the `DoubleField` uses can be replaced with `JafamaDoubleField` or `StrictJafamaDoubleField`. + +```kotlin +import space.kscience.kmath.jafama.* +import space.kscience.kmath.operations.* + +fun main() { + val a = 2.0 + val b = StrictJafamaDoubleField { exp(a) } + println(JafamaDoubleField { b + a }) + println(StrictJafamaDoubleField { ln(b) }) +} +``` + +## Performance + +According to benchmarking data, on Hotspot Jafama functions are 20% faster than JDK math. On GraalVM, they are slower. + +
+Raw data: + +**Hotspot** + +``` +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench + +Warm-up 1: 11.447 ops/s +Iteration 1: 13.354 ops/s +Iteration 2: 14.237 ops/s +Iteration 3: 14.708 ops/s +Iteration 4: 14.629 ops/s +Iteration 5: 14.692 ops/s + +14.324 ±(99.9%) 2.217 ops/s [Average] + (min, avg, max) = (13.354, 14.324, 14.708), stdev = 0.576 + CI (99.9%): [12.107, 16.541] (assumes normal distribution) + +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench + +Warm-up 1: 15.628 ops/s +Iteration 1: 15.991 ops/s +Iteration 2: 16.633 ops/s +Iteration 3: 16.583 ops/s +Iteration 4: 16.716 ops/s +Iteration 5: 16.762 ops/s + +16.537 ±(99.9%) 1.205 ops/s [Average] + (min, avg, max) = (15.991, 16.537, 16.762), stdev = 0.313 + CI (99.9%): [15.332, 17.743] (assumes normal distribution) + +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench + +Warm-up 1: 13.378 ops/s +Iteration 1: 15.049 ops/s +Iteration 2: 14.468 ops/s +Iteration 3: 14.469 ops/s +Iteration 4: 14.753 ops/s +Iteration 5: 14.958 ops/s + +14.739 ±(99.9%) 1.038 ops/s [Average] + (min, avg, max) = (14.468, 14.739, 15.049), stdev = 0.269 + CI (99.9%): [13.701, 15.777] (assumes normal distribution) +``` + +**GraalVM** + +``` +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench + +Warm-up 1: 14.357 ops/s +Iteration 1: 14.768 ops/s +Iteration 2: 14.922 ops/s +Iteration 3: 14.966 ops/s +Iteration 4: 14.805 ops/s +Iteration 5: 14.520 ops/s + +14.796 ±(99.9%) 0.671 ops/s [Average] + (min, avg, max) = (14.520, 14.796, 14.966), stdev = 0.174 + CI (99.9%): [14.125, 15.468] (assumes normal distribution) + +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench + +Warm-up 1: 11.592 ops/s +Iteration 1: 12.174 ops/s +Iteration 2: 11.734 ops/s +Iteration 3: 11.939 ops/s +Iteration 4: 12.026 ops/s +Iteration 5: 12.221 ops/s + +12.019 ±(99.9%) 0.752 ops/s [Average] + (min, avg, max) = (11.734, 12.019, 12.221), stdev = 0.195 + CI (99.9%): [11.267, 12.771] (assumes normal distribution) + +jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench + +Warm-up 1: 12.097 ops/s +Iteration 1: 13.072 ops/s +Iteration 2: 13.112 ops/s +Iteration 3: 13.103 ops/s +Iteration 4: 12.950 ops/s +Iteration 5: 13.011 ops/s + +13.049 ±(99.9%) 0.263 ops/s [Average] + (min, avg, max) = (12.950, 13.049, 13.112), stdev = 0.068 + CI (99.9%): [12.787, 13.312] (assumes normal distribution) +``` + +
diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt index f37d8e7b3..cf6f9471d 100644 --- a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt @@ -1,17 +1,21 @@ package space.kscience.kmath.jafama -import space.kscience.kmath.operations.* -import net.jafama.* +import net.jafama.FastMath +import net.jafama.StrictFastMath +import space.kscience.kmath.operations.ExtendedField +import space.kscience.kmath.operations.Norm +import space.kscience.kmath.operations.PowerOperations +import space.kscience.kmath.operations.ScaleOperations /** * A field for [Double] (using FastMath) without boxing. Does not produce appropriate field element. */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object JafamaDoubleField : ExtendedField, Norm, ScaleOperations { - public override val zero: Double get() = 0.0 - public override val one: Double get() = 1.0 + public override inline val zero: Double get() = 0.0 + public override inline val one: Double get() = 1.0 - public override fun number(value: Number): Double = value.toDouble() + public override inline fun number(value: Number): Double = value.toDouble() public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double = when (operation) { @@ -19,38 +23,39 @@ public object JafamaDoubleField : ExtendedField, Norm, S else -> super.binaryOperationFunction(operation) } - public override fun add(a: Double, b: Double): Double = a + b + public override inline fun add(a: Double, b: Double): Double = a + b - public override fun multiply(a: Double, b: Double): Double = a * b - public override fun divide(a: Double, b: Double): Double = a / b + public override inline fun multiply(a: Double, b: Double): Double = a * b + public override inline fun divide(a: Double, b: Double): Double = a / b - public override fun scale(a: Double, value: Double): Double = a * value + public override inline fun scale(a: Double, value: Double): Double = a * value - public override fun sin(arg: Double): Double = FastMath.sin(arg) - public override fun cos(arg: Double): Double = FastMath.cos(arg) - public override fun tan(arg: Double): Double = FastMath.tan(arg) - public override fun acos(arg: Double): Double = FastMath.acos(arg) - public override fun asin(arg: Double): Double = FastMath.asin(arg) - public override fun atan(arg: Double): Double = FastMath.atan(arg) + public override inline fun sin(arg: Double): Double = FastMath.sin(arg) + public override inline fun cos(arg: Double): Double = FastMath.cos(arg) + public override inline fun tan(arg: Double): Double = FastMath.tan(arg) + public override inline fun acos(arg: Double): Double = FastMath.acos(arg) + public override inline fun asin(arg: Double): Double = FastMath.asin(arg) + public override inline fun atan(arg: Double): Double = FastMath.atan(arg) - public override fun sinh(arg: Double): Double = FastMath.sinh(arg) - public override fun cosh(arg: Double): Double = FastMath.cosh(arg) - public override fun tanh(arg: Double): Double = FastMath.tanh(arg) - public override fun asinh(arg: Double): Double = FastMath.asinh(arg) - public override fun acosh(arg: Double): Double = FastMath.acosh(arg) - public override fun atanh(arg: Double): Double = FastMath.atanh(arg) + public override inline fun sinh(arg: Double): Double = FastMath.sinh(arg) + public override inline fun cosh(arg: Double): Double = FastMath.cosh(arg) + public override inline fun tanh(arg: Double): Double = FastMath.tanh(arg) + public override inline fun asinh(arg: Double): Double = FastMath.asinh(arg) + public override inline fun acosh(arg: Double): Double = FastMath.acosh(arg) + public override inline fun atanh(arg: Double): Double = FastMath.atanh(arg) - public override fun power(arg: Double, pow: Number): Double = FastMath.pow(arg, pow.toDouble()) - public override fun exp(arg: Double): Double = FastMath.exp(arg) - public override fun ln(arg: Double): Double = FastMath.log(arg) + public override inline fun sqrt(arg: Double): Double = FastMath.sqrt(arg) + public override inline fun power(arg: Double, pow: Number): Double = FastMath.pow(arg, pow.toDouble()) + public override inline fun exp(arg: Double): Double = FastMath.exp(arg) + public override inline fun ln(arg: Double): Double = FastMath.log(arg) - public override fun norm(arg: Double): Double = FastMath.abs(arg) + public override inline fun norm(arg: Double): Double = FastMath.abs(arg) - public override fun Double.unaryMinus(): Double = -this - public override fun Double.plus(b: Double): Double = this + b - public override fun Double.minus(b: Double): Double = this - b - public override fun Double.times(b: Double): Double = this * b - public override fun Double.div(b: Double): Double = this / b + public override inline fun Double.unaryMinus(): Double = -this + public override inline fun Double.plus(b: Double): Double = this + b + public override inline fun Double.minus(b: Double): Double = this - b + public override inline fun Double.times(b: Double): Double = this * b + public override inline fun Double.div(b: Double): Double = this / b } /** @@ -58,10 +63,10 @@ public object JafamaDoubleField : ExtendedField, Norm, S */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object StrictJafamaDoubleField : ExtendedField, Norm, ScaleOperations { - public override val zero: Double get() = 0.0 - public override val one: Double get() = 1.0 + public override inline val zero: Double get() = 0.0 + public override inline val one: Double get() = 1.0 - public override fun number(value: Number): Double = value.toDouble() + public override inline fun number(value: Number): Double = value.toDouble() public override fun binaryOperationFunction(operation: String): (left: Double, right: Double) -> Double = when (operation) { @@ -69,38 +74,37 @@ public object StrictJafamaDoubleField : ExtendedField, Norm super.binaryOperationFunction(operation) } - public override fun add(a: Double, b: Double): Double = a + b + public override inline fun add(a: Double, b: Double): Double = a + b - public override fun multiply(a: Double, b: Double): Double = a * b - public override fun divide(a: Double, b: Double): Double = a / b + public override inline fun multiply(a: Double, b: Double): Double = a * b + public override inline fun divide(a: Double, b: Double): Double = a / b - public override fun scale(a: Double, value: Double): Double = a * value + public override inline fun scale(a: Double, value: Double): Double = a * value - public override fun sin(arg: Double): Double = StrictFastMath.sin(arg) - public override fun cos(arg: Double): Double = StrictFastMath.cos(arg) - public override fun tan(arg: Double): Double = StrictFastMath.tan(arg) - public override fun acos(arg: Double): Double = StrictFastMath.acos(arg) - public override fun asin(arg: Double): Double = StrictFastMath.asin(arg) - public override fun atan(arg: Double): Double = StrictFastMath.atan(arg) + public override inline fun sin(arg: Double): Double = StrictFastMath.sin(arg) + public override inline fun cos(arg: Double): Double = StrictFastMath.cos(arg) + public override inline fun tan(arg: Double): Double = StrictFastMath.tan(arg) + public override inline fun acos(arg: Double): Double = StrictFastMath.acos(arg) + public override inline fun asin(arg: Double): Double = StrictFastMath.asin(arg) + public override inline fun atan(arg: Double): Double = StrictFastMath.atan(arg) - public override fun sinh(arg: Double): Double = StrictFastMath.sinh(arg) - public override fun cosh(arg: Double): Double = StrictFastMath.cosh(arg) - public override fun tanh(arg: Double): Double = StrictFastMath.tanh(arg) - public override fun asinh(arg: Double): Double = StrictFastMath.asinh(arg) - public override fun acosh(arg: Double): Double = StrictFastMath.acosh(arg) - public override fun atanh(arg: Double): Double = StrictFastMath.atanh(arg) + public override inline fun sinh(arg: Double): Double = StrictFastMath.sinh(arg) + public override inline fun cosh(arg: Double): Double = StrictFastMath.cosh(arg) + public override inline fun tanh(arg: Double): Double = StrictFastMath.tanh(arg) + public override inline fun asinh(arg: Double): Double = StrictFastMath.asinh(arg) + public override inline fun acosh(arg: Double): Double = StrictFastMath.acosh(arg) + public override inline fun atanh(arg: Double): Double = StrictFastMath.atanh(arg) - public override fun power(arg: Double, pow: Number): Double = StrictFastMath.pow(arg, pow.toDouble()) - public override fun exp(arg: Double): Double = StrictFastMath.exp(arg) - public override fun ln(arg: Double): Double = StrictFastMath.log(arg) + public override inline fun sqrt(arg: Double): Double = StrictFastMath.sqrt(arg) + public override inline fun power(arg: Double, pow: Number): Double = StrictFastMath.pow(arg, pow.toDouble()) + public override inline fun exp(arg: Double): Double = StrictFastMath.exp(arg) + public override inline fun ln(arg: Double): Double = StrictFastMath.log(arg) - public override fun norm(arg: Double): Double = StrictFastMath.abs(arg) + public override inline fun norm(arg: Double): Double = StrictFastMath.abs(arg) - public override fun Double.unaryMinus(): Double = -this - public override fun Double.plus(b: Double): Double = this + b - public override fun Double.minus(b: Double): Double = this - b - public override fun Double.times(b: Double): Double = this * b - public override fun Double.div(b: Double): Double = this / b + public override inline fun Double.unaryMinus(): Double = -this + public override inline fun Double.plus(b: Double): Double = this + b + public override inline fun Double.minus(b: Double): Double = this - b + public override inline fun Double.times(b: Double): Double = this * b + public override inline fun Double.div(b: Double): Double = this / b } - - From 45f158817551cf277688d42c3cdb8994f6401023 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 15 Jun 2021 13:18:40 +0700 Subject: [PATCH 388/393] Generated benchmarking reports --- benchmarks/build.gradle.kts | 8 +- .../kmath/benchmarks/JafamaBenchmark.kt | 6 +- buildSrc/build.gradle.kts | 16 ++- .../kscience/kmath/benchmarks/JmhReport.kt | 60 ++++++++++ .../benchmarks/addBenchmarkProperties.kt | 105 ++++++++++++++++++ kmath-ast/build.gradle.kts | 12 +- kmath-jafama/README.md | 97 +++------------- kmath-jafama/docs/README-TEMPLATE.md | 93 +--------------- settings.gradle.kts | 2 +- 9 files changed, 210 insertions(+), 189 deletions(-) create mode 100644 buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt create mode 100644 buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index f171437d3..2198ac5d6 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -1,3 +1,7 @@ +@file:Suppress("UNUSED_VARIABLE") + +import space.kscience.kmath.benchmarks.addBenchmarkProperties + plugins { kotlin("multiplatform") kotlin("plugin.allopen") @@ -32,7 +36,7 @@ kotlin { implementation(project(":kmath-dimensions")) implementation(project(":kmath-for-real")) implementation(project(":kmath-jafama")) - implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.0") + implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.1") } } @@ -130,3 +134,5 @@ tasks.withType { readme { maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL } + +addBenchmarkProperties() diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt index 260eea2b6..24a730375 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt @@ -18,17 +18,17 @@ import kotlin.random.Random @State(Scope.Benchmark) internal class JafamaBenchmark { @Benchmark - fun jafamaBench(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x -> + fun jafama(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x -> JafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) } } @Benchmark - fun coreBench(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x -> + fun core(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x -> DoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) } } @Benchmark - fun strictJafamaBench(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x -> + fun strictJafama(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x -> StrictJafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 7ca4df19d..8ff1c4369 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,5 +1,19 @@ plugins { `kotlin-dsl` + kotlin("plugin.serialization") version "1.4.31" } -repositories.mavenCentral() +repositories { + gradlePluginPortal() + mavenCentral() +} + +dependencies { + api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0") + api("ru.mipt.npm:gradle-tools:0.9.10") + api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.3.1") +} + +kotlin.sourceSets.all { + languageSettings.useExperimentalAnnotation("kotlin.ExperimentalStdlibApi") +} diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt new file mode 100644 index 000000000..eaa0f59d8 --- /dev/null +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.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.benchmarks + +import kotlinx.serialization.Serializable + +@Serializable +data class JmhReport( + val jmhVersion: String, + val benchmark: String, + val mode: String, + val threads: Int, + val forks: Int, + val jvm: String, + val jvmArgs: List, + val jdkVersion: String, + val vmName: String, + val vmVersion: String, + val warmupIterations: Int, + val warmupTime: String, + val warmupBatchSize: Int, + val measurementIterations: Int, + val measurementTime: String, + val measurementBatchSize: Int, + val params: Map = emptyMap(), + val primaryMetric: PrimaryMetric, + val secondaryMetrics: Map, +) { + interface Metric { + val score: Double + val scoreError: Double + val scoreConfidence: List + val scorePercentiles: Map + val scoreUnit: String + } + + @Serializable + data class PrimaryMetric( + override val score: Double, + override val scoreError: Double, + override val scoreConfidence: List, + override val scorePercentiles: Map, + override val scoreUnit: String, + val rawDataHistogram: List>>>? = null, + val rawData: List>? = null, + ) : Metric + + @Serializable + data class SecondaryMetric( + override val score: Double, + override val scoreError: Double, + override val scoreConfidence: List, + override val scorePercentiles: Map, + override val scoreUnit: String, + val rawData: List>, + ) : Metric +} diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt new file mode 100644 index 000000000..31d952157 --- /dev/null +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt @@ -0,0 +1,105 @@ +/* + * 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.benchmarks + +import kotlinx.serialization.* +import org.gradle.api.Project +import java.time.* +import java.time.format.* +import java.time.temporal.ChronoField.* + +private val ISO_DATE_TIME: DateTimeFormatter = DateTimeFormatterBuilder().run { + parseCaseInsensitive() + appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD) + appendLiteral('-') + appendValue(MONTH_OF_YEAR, 2) + appendLiteral('-') + appendValue(DAY_OF_MONTH, 2) + appendLiteral('T') + appendValue(HOUR_OF_DAY, 2) + appendLiteral('.') + appendValue(MINUTE_OF_HOUR, 2) + optionalStart() + appendLiteral('.') + appendValue(SECOND_OF_MINUTE, 2) + optionalStart() + appendFraction(NANO_OF_SECOND, 0, 9, true) + optionalStart() + appendOffsetId() + optionalStart() + appendLiteral('[') + parseCaseSensitive() + appendZoneRegionId() + appendLiteral(']') + toFormatter() +} + +private fun noun(number: Number, singular: String, plural: String) = if (number.toLong() == 1L) singular else plural + +fun Project.addBenchmarkProperties() { + val benchmarksProject = this + rootProject.subprojects.forEach { p -> + p.extensions.findByType(ru.mipt.npm.gradle.KScienceReadmeExtension::class.java)?.run { + benchmarksProject.extensions.findByType(kotlinx.benchmark.gradle.BenchmarksExtension::class.java)?.configurations?.forEach { cfg -> + // TODO remove this hack when https://github.com/mipt-npm/gradle-tools/pull/15 is merged + @Suppress("UNCHECKED_CAST") + (javaClass.getDeclaredField("properties") + .also { + it.isAccessible = true + }[this] as MutableMap Any?>)["benchmark${cfg.name.replaceFirstChar(Char::uppercase)}"] = + { + val launches = benchmarksProject.buildDir.resolve("reports/benchmarks/${cfg.name}") + + val resDirectory = launches.listFiles()?.maxByOrNull { + LocalDateTime.parse(it.name, ISO_DATE_TIME).atZone(ZoneId.systemDefault()).toInstant() + } + + if (resDirectory == null) { + "> **Can't find appropriate benchmark data. Try generating readme files after running benchmarks**." + } else { + val reports = + kotlinx.serialization.json.Json.decodeFromString>( + resDirectory.resolve("jvm.json").readText() + ) + + buildString { + appendLine("
") + appendLine("") + appendLine("Report for benchmark configuration ${cfg.name}") + appendLine("") + appendLine() + val first = reports.first() + + appendLine("* Run on ${first.vmName} (build ${first.vmVersion}) with Java process:") + appendLine() + appendLine("```") + appendLine("${first.jvm} ${ + first.jvmArgs.joinToString(" ") + }") + appendLine("```") + + appendLine("* JMH ${first.jmhVersion} was used in `${first.mode}` mode with ${first.warmupIterations} warmup ${ + noun(first.warmupIterations, "iteration", "iterations") + } by ${first.warmupTime} and ${first.measurementIterations} measurement ${ + noun(first.measurementIterations, "iteration", "iterations") + } by ${first.measurementTime}.") + + appendLine() + appendLine("| Benchmark | Score |") + appendLine("|:---------:|:-----:|") + + reports.forEach { report -> + appendLine("|`${report.benchmark}`|${report.primaryMetric.score} ± ${report.primaryMetric.scoreError} ${report.primaryMetric.scoreUnit}|") + } + + appendLine("
") + } + } + } + } + } + } +} diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 89647c9e9..8209a0dad 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -62,25 +62,21 @@ readme { feature( id = "expression-language", - description = "Expression language and its parser", ref = "src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt" - ) + ) { "Expression language and its parser" } feature( id = "mst-jvm-codegen", - description = "Dynamic MST to JVM bytecode compiler", ref = "src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt" - ) + ) { "Dynamic MST to JVM bytecode compiler" } feature( id = "mst-js-codegen", - description = "Dynamic MST to JS compiler", ref = "src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt" - ) + ) { "Dynamic MST to JS compiler" } feature( id = "rendering", - description = "Extendable MST rendering", ref = "src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt" - ) + ) { "Extendable MST rendering" } } diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md index 9b439c5c2..ef8fcd352 100644 --- a/kmath-jafama/README.md +++ b/kmath-jafama/README.md @@ -50,95 +50,24 @@ fun main() { ## Performance -According to benchmarking data, on Hotspot Jafama functions are 20% faster than JDK math. On GraalVM, they are slower. +According to KMath benchmarks on GraalVM, Jafama functions are slower than JDK math; however, there are indications that on Hotspot Jafama is a bit faster.
-Raw data: + +Report for benchmark configuration jafamaDouble + -**Hotspot** +* Run on OpenJDK 64-Bit Server VM (build 11.0.11+8-jvmci-21.1-b05) with Java process: ``` -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench - -Warm-up 1: 11.447 ops/s -Iteration 1: 13.354 ops/s -Iteration 2: 14.237 ops/s -Iteration 3: 14.708 ops/s -Iteration 4: 14.629 ops/s -Iteration 5: 14.692 ops/s - -14.324 ±(99.9%) 2.217 ops/s [Average] - (min, avg, max) = (13.354, 14.324, 14.708), stdev = 0.576 - CI (99.9%): [12.107, 16.541] (assumes normal distribution) - -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench - -Warm-up 1: 15.628 ops/s -Iteration 1: 15.991 ops/s -Iteration 2: 16.633 ops/s -Iteration 3: 16.583 ops/s -Iteration 4: 16.716 ops/s -Iteration 5: 16.762 ops/s - -16.537 ±(99.9%) 1.205 ops/s [Average] - (min, avg, max) = (15.991, 16.537, 16.762), stdev = 0.313 - CI (99.9%): [15.332, 17.743] (assumes normal distribution) - -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench - -Warm-up 1: 13.378 ops/s -Iteration 1: 15.049 ops/s -Iteration 2: 14.468 ops/s -Iteration 3: 14.469 ops/s -Iteration 4: 14.753 ops/s -Iteration 5: 14.958 ops/s - -14.739 ±(99.9%) 1.038 ops/s [Average] - (min, avg, max) = (14.468, 14.739, 15.049), stdev = 0.269 - CI (99.9%): [13.701, 15.777] (assumes normal distribution) -``` - -**GraalVM** - -``` -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench - -Warm-up 1: 14.357 ops/s -Iteration 1: 14.768 ops/s -Iteration 2: 14.922 ops/s -Iteration 3: 14.966 ops/s -Iteration 4: 14.805 ops/s -Iteration 5: 14.520 ops/s - -14.796 ±(99.9%) 0.671 ops/s [Average] - (min, avg, max) = (14.520, 14.796, 14.966), stdev = 0.174 - CI (99.9%): [14.125, 15.468] (assumes normal distribution) - -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench - -Warm-up 1: 11.592 ops/s -Iteration 1: 12.174 ops/s -Iteration 2: 11.734 ops/s -Iteration 3: 11.939 ops/s -Iteration 4: 12.026 ops/s -Iteration 5: 12.221 ops/s - -12.019 ±(99.9%) 0.752 ops/s [Average] - (min, avg, max) = (11.734, 12.019, 12.221), stdev = 0.195 - CI (99.9%): [11.267, 12.771] (assumes normal distribution) - -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench - -Warm-up 1: 12.097 ops/s -Iteration 1: 13.072 ops/s -Iteration 2: 13.112 ops/s -Iteration 3: 13.103 ops/s -Iteration 4: 12.950 ops/s -Iteration 5: 13.011 ops/s - -13.049 ±(99.9%) 0.263 ops/s [Average] - (min, avg, max) = (12.950, 13.049, 13.112), stdev = 0.068 - CI (99.9%): [12.787, 13.312] (assumes normal distribution) +/home/commandertvis/graalvm-ce-java11/bin/java -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCIProduct -XX:-UnlockExperimentalVMOptions -XX:ThreadPriorityPolicy=1 -javaagent:/home/commandertvis/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-coroutines-core-jvm/1.5.0/d8cebccdcddd029022aa8646a5a953ff88b13ac8/kotlinx-coroutines-core-jvm-1.5.0.jar -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -ea ``` +* JMH 1.21 was used in `thrpt` mode with 1 warmup iteration by 1000 ms and 5 measurement iterations by 1000 ms. +| Benchmark | Score | +|:---------:|:-----:| +|`space.kscience.kmath.benchmarks.JafamaBenchmark.core`|14.296120859512893 ± 0.36462633435888736 ops/s| +|`space.kscience.kmath.benchmarks.JafamaBenchmark.jafama`|11.431566395649781 ± 2.570896777898243 ops/s| +|`space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafama`|11.746020495694117 ± 6.205909559197869 ops/s|
+ diff --git a/kmath-jafama/docs/README-TEMPLATE.md b/kmath-jafama/docs/README-TEMPLATE.md index fa58f7697..54348467b 100644 --- a/kmath-jafama/docs/README-TEMPLATE.md +++ b/kmath-jafama/docs/README-TEMPLATE.md @@ -24,95 +24,6 @@ fun main() { ## Performance -According to benchmarking data, on Hotspot Jafama functions are 20% faster than JDK math. On GraalVM, they are slower. +According to KMath benchmarks on GraalVM, Jafama functions are slower than JDK math; however, there are indications that on Hotspot Jafama is a bit faster. -
-Raw data: - -**Hotspot** - -``` -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench - -Warm-up 1: 11.447 ops/s -Iteration 1: 13.354 ops/s -Iteration 2: 14.237 ops/s -Iteration 3: 14.708 ops/s -Iteration 4: 14.629 ops/s -Iteration 5: 14.692 ops/s - -14.324 ±(99.9%) 2.217 ops/s [Average] - (min, avg, max) = (13.354, 14.324, 14.708), stdev = 0.576 - CI (99.9%): [12.107, 16.541] (assumes normal distribution) - -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench - -Warm-up 1: 15.628 ops/s -Iteration 1: 15.991 ops/s -Iteration 2: 16.633 ops/s -Iteration 3: 16.583 ops/s -Iteration 4: 16.716 ops/s -Iteration 5: 16.762 ops/s - -16.537 ±(99.9%) 1.205 ops/s [Average] - (min, avg, max) = (15.991, 16.537, 16.762), stdev = 0.313 - CI (99.9%): [15.332, 17.743] (assumes normal distribution) - -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench - -Warm-up 1: 13.378 ops/s -Iteration 1: 15.049 ops/s -Iteration 2: 14.468 ops/s -Iteration 3: 14.469 ops/s -Iteration 4: 14.753 ops/s -Iteration 5: 14.958 ops/s - -14.739 ±(99.9%) 1.038 ops/s [Average] - (min, avg, max) = (14.468, 14.739, 15.049), stdev = 0.269 - CI (99.9%): [13.701, 15.777] (assumes normal distribution) -``` - -**GraalVM** - -``` -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.coreBench - -Warm-up 1: 14.357 ops/s -Iteration 1: 14.768 ops/s -Iteration 2: 14.922 ops/s -Iteration 3: 14.966 ops/s -Iteration 4: 14.805 ops/s -Iteration 5: 14.520 ops/s - -14.796 ±(99.9%) 0.671 ops/s [Average] - (min, avg, max) = (14.520, 14.796, 14.966), stdev = 0.174 - CI (99.9%): [14.125, 15.468] (assumes normal distribution) - -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.jafamaBench - -Warm-up 1: 11.592 ops/s -Iteration 1: 12.174 ops/s -Iteration 2: 11.734 ops/s -Iteration 3: 11.939 ops/s -Iteration 4: 12.026 ops/s -Iteration 5: 12.221 ops/s - -12.019 ±(99.9%) 0.752 ops/s [Average] - (min, avg, max) = (11.734, 12.019, 12.221), stdev = 0.195 - CI (99.9%): [11.267, 12.771] (assumes normal distribution) - -jvm: space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafamaBench - -Warm-up 1: 12.097 ops/s -Iteration 1: 13.072 ops/s -Iteration 2: 13.112 ops/s -Iteration 3: 13.103 ops/s -Iteration 4: 12.950 ops/s -Iteration 5: 13.011 ops/s - -13.049 ±(99.9%) 0.263 ops/s [Average] - (min, avg, max) = (12.950, 13.049, 13.112), stdev = 0.068 - CI (99.9%): [12.787, 13.312] (assumes normal distribution) -``` - -
+${benchmarkJafamaDouble} diff --git a/settings.gradle.kts b/settings.gradle.kts index 15a6a176c..710017588 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,7 +5,7 @@ pluginManagement { gradlePluginPortal() } - val toolsVersion = "0.9.9" + val toolsVersion = "0.9.10" val kotlinVersion = "1.5.0" plugins { From 94c58b7749e5e4ea69d167cda4ea282fa3d9077f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 15 Jun 2021 13:45:08 +0300 Subject: [PATCH 389/393] Fix Univariate histogram filling --- CHANGELOG.md | 1 + build.gradle.kts | 2 +- .../kmath/histogram/TreeHistogramSpace.kt | 89 ++++++++++--------- .../kmath/histogram/UnivariateHistogram.kt | 6 +- .../kmath/histogram/TreeHistogramTest.kt | 24 +++++ 5 files changed, 77 insertions(+), 45 deletions(-) create mode 100644 kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f7b6b529..12540821e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ ### Fixed - Ring inherits RingOperations, not GroupOperations +- Univariate histogram filling ### Security diff --git a/build.gradle.kts b/build.gradle.kts index 86394d792..9978281f2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,7 +17,7 @@ allprojects { } group = "space.kscience" - version = "0.3.0-dev-13" + version = "0.3.0-dev-14" } subprojects { diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt index 6ae8b5ee3..8d05df68a 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramSpace.kt @@ -35,51 +35,56 @@ public class TreeHistogram( override val bins: Collection get() = binMap.values } +@OptIn(UnstableKMathAPI::class) +private class TreeHistogramBuilder(val binFactory: (Double) -> UnivariateDomain) : UnivariateHistogramBuilder { + + private class BinCounter(val domain: UnivariateDomain, val counter: Counter = Counter.real()) : + ClosedFloatingPointRange by domain.range + + private val bins: TreeMap = TreeMap() + + fun get(value: Double): BinCounter? = bins.getBin(value) + + fun createBin(value: Double): BinCounter { + val binDefinition = binFactory(value) + val newBin = BinCounter(binDefinition) + synchronized(this) { bins[binDefinition.center] = newBin } + return newBin + } + + /** + * Thread safe put operation + */ + override fun putValue(at: Double, value: Double) { + (get(at) ?: createBin(at)).apply { + counter.add(value) + } + } + + override fun putValue(point: Buffer, value: Number) { + require(point.size == 1) { "Only points with single value could be used in univariate histogram" } + putValue(point[0], value.toDouble()) + } + + fun build(): TreeHistogram { + val map = bins.mapValuesTo(TreeMap()) { (_, binCounter) -> + val count = binCounter.counter.value + UnivariateBin(binCounter.domain, count, sqrt(count)) + } + return TreeHistogram(map) + } +} + /** * A space for univariate histograms with variable bin borders based on a tree map */ @UnstableKMathAPI public class TreeHistogramSpace( - public val binFactory: (Double) -> UnivariateDomain, + private val binFactory: (Double) -> UnivariateDomain, ) : Group, ScaleOperations { - private class BinCounter(val domain: UnivariateDomain, val counter: Counter = Counter.real()) : - ClosedFloatingPointRange by domain.range - - public fun produce(builder: UnivariateHistogramBuilder.() -> Unit): UnivariateHistogram { - val bins: TreeMap = TreeMap() - val hBuilder = object : UnivariateHistogramBuilder { - - fun get(value: Double): BinCounter? = bins.getBin(value) - - fun createBin(value: Double): BinCounter { - val binDefinition = binFactory(value) - val newBin = BinCounter(binDefinition) - synchronized(this) { bins[binDefinition.center] = newBin } - return newBin - } - - /** - * Thread safe put operation - */ - override fun putValue(at: Double, value: Double) { - (get(at) ?: createBin(at)).apply { - counter.add(value) - } - } - - override fun putValue(point: Buffer, value: Number) { - put(point[0], value.toDouble()) - } - } - hBuilder.apply(builder) - val resBins = TreeMap() - bins.forEach { (key, binCounter) -> - val count = binCounter.counter.value - resBins[key] = UnivariateBin(binCounter.domain, count, sqrt(count)) - } - return TreeHistogram(resBins) - } + public fun fill(block: UnivariateHistogramBuilder.() -> Unit): UnivariateHistogram = + TreeHistogramBuilder(binFactory).apply(block).build() override fun add( a: UnivariateHistogram, @@ -89,7 +94,8 @@ public class TreeHistogramSpace( // require(b.context == this) { "Histogram $b does not belong to this context" } val bins = TreeMap().apply { (a.bins.map { it.domain } union b.bins.map { it.domain }).forEach { def -> - put(def.center, + put( + def.center, UnivariateBin( def, value = (a[def.center]?.value ?: 0.0) + (b[def.center]?.value ?: 0.0), @@ -105,7 +111,8 @@ public class TreeHistogramSpace( override fun scale(a: UnivariateHistogram, value: Double): UnivariateHistogram { val bins = TreeMap().apply { a.bins.forEach { bin -> - put(bin.domain.center, + put( + bin.domain.center, UnivariateBin( bin.domain, value = bin.value * value.toDouble(), @@ -120,7 +127,7 @@ public class TreeHistogramSpace( override fun UnivariateHistogram.unaryMinus(): UnivariateHistogram = this * (-1) - override val zero: UnivariateHistogram = produce { } + override val zero: UnivariateHistogram by lazy { fill { } } public companion object { /** diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt index 70125e22e..0ad96ad46 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/UnivariateHistogram.kt @@ -13,7 +13,7 @@ import space.kscience.kmath.structures.asSequence @UnstableKMathAPI public val UnivariateDomain.center: Double - get() = (range.endInclusive - range.start) / 2 + get() = (range.endInclusive + range.start) / 2 /** * A univariate bin based an a range @@ -45,7 +45,7 @@ public interface UnivariateHistogram : Histogram{ binSize: Double, start: Double = 0.0, builder: UnivariateHistogramBuilder.() -> Unit, - ): UnivariateHistogram = TreeHistogramSpace.uniform(binSize, start).produce(builder) + ): UnivariateHistogram = TreeHistogramSpace.uniform(binSize, start).fill(builder) /** * Build and fill a histogram with custom borders. Returns a read-only histogram. @@ -53,7 +53,7 @@ public interface UnivariateHistogram : Histogram{ public fun custom( borders: DoubleArray, builder: UnivariateHistogramBuilder.() -> Unit, - ): UnivariateHistogram = TreeHistogramSpace.custom(borders).produce(builder) + ): UnivariateHistogram = TreeHistogramSpace.custom(borders).fill(builder) } } diff --git a/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt b/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt new file mode 100644 index 000000000..28a1b03cb --- /dev/null +++ b/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt @@ -0,0 +1,24 @@ +/* + * 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.histogram + +import org.junit.jupiter.api.Test +import kotlin.random.Random +import kotlin.test.assertTrue + +class TreeHistogramTest { + + @Test + fun normalFill() { + val histogram = UnivariateHistogram.uniform(0.1) { + repeat(100_000) { + putValue(Random.nextDouble()) + } + } + + assertTrue { histogram.bins.count() > 10 } + } +} \ No newline at end of file From 5d5f84ad55e65af19c8b4a8daa549ba306a9f722 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 15 Jun 2021 20:37:40 +0700 Subject: [PATCH 390/393] Some refactoring of AST rendering --- .../kmath/ast/rendering/MathRenderer.kt | 6 +- .../kscience/kmath/ast/rendering/features.kt | 41 +++++---- .../ast/rendering/{stages.kt => phases.kt} | 89 ++++++++++--------- 3 files changed, 68 insertions(+), 68 deletions(-) rename kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/{stages.kt => phases.kt} (76%) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index c33f95483..68d829724 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -54,7 +54,7 @@ public open class FeaturedMathRenderer(public val features: List) @UnstableKMathAPI public open class FeaturedMathRendererWithPostProcess( features: List, - public val stages: List, + public val stages: List, ) : FeaturedMathRenderer(features) { public override fun render(mst: MST): MathSyntax { val res = super.render(mst) @@ -65,7 +65,7 @@ public open class FeaturedMathRendererWithPostProcess( /** * Logical unit of [MathSyntax] post-processing. */ - public fun interface PostProcessStage { + public fun interface PostProcessPhase { /** * Performs the specified action over [MathSyntax]. */ @@ -102,7 +102,7 @@ public open class FeaturedMathRendererWithPostProcess( // Printing terminal nodes as string PrintNumeric, - PrintSymbolic, + PrintSymbol, ), listOf( BetterExponent, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index 863825799..a2f42d1bf 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -13,15 +13,14 @@ import space.kscience.kmath.operations.* import kotlin.reflect.KClass /** - * Prints any [MST.Symbolic] as a [SymbolSyntax] containing the [MST.Symbolic.value] of it. + * Prints any [Symbol] as a [SymbolSyntax] containing the [Symbol.value] of it. * * @author Iaroslav Postovalov */ @UnstableKMathAPI -public object PrintSymbolic : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): SymbolSyntax? = - if (node !is Symbol) null - else SymbolSyntax(string = node.identity) +public val PrintSymbol: RenderFeature = RenderFeature { _, node -> + if (node !is Symbol) null + else SymbolSyntax(string = node.identity) } /** @@ -30,8 +29,8 @@ public object PrintSymbolic : RenderFeature { * @author Iaroslav Postovalov */ @UnstableKMathAPI -public object PrintNumeric : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): NumberSyntax? = if (node !is MST.Numeric) +public val PrintNumeric: RenderFeature = RenderFeature { _, node -> + if (node !is MST.Numeric) null else NumberSyntax(string = node.value.toString()) @@ -141,7 +140,7 @@ public class PrettyPrintIntegers(public val types: Set>) : Re */ @UnstableKMathAPI public class PrettyPrintPi(public val symbols: Set) : RenderFeature { - public override fun render(renderer: FeaturedMathRenderer, node: MST): SpecialSymbolSyntax? = + public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? = if (node !is Symbol || node.identity !in symbols) null else @@ -203,7 +202,7 @@ public abstract class Binary(public val operations: Collection?) : Rende */ @UnstableKMathAPI public class BinaryPlus(operations: Collection?) : Binary(operations) { - public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryPlusSyntax = + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryPlusSyntax( operation = node.operation, left = OperandSyntax(parent.render(node.left), true), @@ -225,7 +224,7 @@ public class BinaryPlus(operations: Collection?) : Binary(operations) { */ @UnstableKMathAPI public class BinaryMinus(operations: Collection?) : Binary(operations) { - public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryMinusSyntax = + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryMinusSyntax( operation = node.operation, left = OperandSyntax(operand = parent.render(node.left), parentheses = true), @@ -247,7 +246,7 @@ public class BinaryMinus(operations: Collection?) : Binary(operations) { */ @UnstableKMathAPI public class UnaryPlus(operations: Collection?) : Unary(operations) { - public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryPlusSyntax = UnaryPlusSyntax( + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax( operation = node.operation, operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), ) @@ -267,7 +266,7 @@ public class UnaryPlus(operations: Collection?) : Unary(operations) { */ @UnstableKMathAPI public class UnaryMinus(operations: Collection?) : Unary(operations) { - public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryMinusSyntax = UnaryMinusSyntax( + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax( operation = node.operation, operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), ) @@ -287,7 +286,7 @@ public class UnaryMinus(operations: Collection?) : Unary(operations) { */ @UnstableKMathAPI public class Fraction(operations: Collection?) : Binary(operations) { - public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = FractionSyntax( + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax( operation = node.operation, left = OperandSyntax(operand = parent.render(node.left), parentheses = true), right = OperandSyntax(operand = parent.render(node.right), parentheses = true), @@ -309,7 +308,7 @@ public class Fraction(operations: Collection?) : Binary(operations) { */ @UnstableKMathAPI public class BinaryOperator(operations: Collection?) : Binary(operations) { - public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryOperatorSyntax = + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryOperatorSyntax( operation = node.operation, prefix = OperatorNameSyntax(name = node.operation), @@ -332,7 +331,7 @@ public class BinaryOperator(operations: Collection?) : Binary(operations */ @UnstableKMathAPI public class UnaryOperator(operations: Collection?) : Unary(operations) { - public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( operation = node.operation, prefix = OperatorNameSyntax(node.operation), @@ -354,7 +353,7 @@ public class UnaryOperator(operations: Collection?) : Unary(operations) */ @UnstableKMathAPI public class Power(operations: Collection?) : Binary(operations) { - public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): SuperscriptSyntax = + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = SuperscriptSyntax( operation = node.operation, left = OperandSyntax(parent.render(node.left), true), @@ -374,7 +373,7 @@ public class Power(operations: Collection?) : Binary(operations) { */ @UnstableKMathAPI public class SquareRoot(operations: Collection?) : Unary(operations) { - public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): RadicalSyntax = + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = RadicalSyntax(operation = node.operation, operand = parent.render(node.value)) public companion object { @@ -392,7 +391,7 @@ public class SquareRoot(operations: Collection?) : Unary(operations) { */ @UnstableKMathAPI public class Exponent(operations: Collection?) : Unary(operations) { - public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): ExponentSyntax = ExponentSyntax( + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax( operation = node.operation, operand = OperandSyntax(operand = parent.render(node.value), parentheses = true), useOperatorForm = true, @@ -413,7 +412,7 @@ public class Exponent(operations: Collection?) : Unary(operations) { */ @UnstableKMathAPI public class Multiplication(operations: Collection?) : Binary(operations) { - public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MultiplicationSyntax = + public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = MultiplicationSyntax( operation = node.operation, left = OperandSyntax(operand = parent.render(node.left), parentheses = true), @@ -436,7 +435,7 @@ public class Multiplication(operations: Collection?) : Binary(operations */ @UnstableKMathAPI public class InverseTrigonometricOperations(operations: Collection?) : Unary(operations) { - public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( operation = node.operation, prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "arc")), @@ -463,7 +462,7 @@ public class InverseTrigonometricOperations(operations: Collection?) : U */ @UnstableKMathAPI public class InverseHyperbolicOperations(operations: Collection?) : Unary(operations) { - public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax = + public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( operation = node.operation, prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "ar")), diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt similarity index 76% rename from kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt rename to kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt index 1f31af853..6da4994a6 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/stages.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess.PostProcessPhase import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.FieldOperations import space.kscience.kmath.operations.GroupOperations @@ -17,8 +18,8 @@ import space.kscience.kmath.operations.RingOperations * @author Iaroslav Postovalov */ @UnstableKMathAPI -public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage { - public override fun perform(node: MathSyntax): Unit = when (node) { +public val BetterMultiplication: PostProcessPhase = PostProcessPhase { node -> + fun perform(node: MathSyntax): Unit = when (node) { is NumberSyntax -> Unit is SymbolSyntax -> Unit is OperatorNameSyntax -> Unit @@ -81,6 +82,8 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro perform(node.right) } } + + perform(node) } /** @@ -89,68 +92,68 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro * @author Iaroslav Postovalov */ @UnstableKMathAPI -public object BetterFraction : FeaturedMathRendererWithPostProcess.PostProcessStage { - private fun perform0(node: MathSyntax, infix: Boolean = false): Unit = when (node) { +public val BetterFraction: PostProcessPhase = PostProcessPhase { node -> + fun perform(node: MathSyntax, infix: Boolean = false): Unit = when (node) { is NumberSyntax -> Unit is SymbolSyntax -> Unit is OperatorNameSyntax -> Unit is SpecialSymbolSyntax -> Unit - is OperandSyntax -> perform0(node.operand, infix) + is OperandSyntax -> perform(node.operand, infix) is UnaryOperatorSyntax -> { - perform0(node.prefix, infix) - perform0(node.operand, infix) + perform(node.prefix, infix) + perform(node.operand, infix) } - is UnaryPlusSyntax -> perform0(node.operand, infix) - is UnaryMinusSyntax -> perform0(node.operand, infix) - is RadicalSyntax -> perform0(node.operand, infix) - is ExponentSyntax -> perform0(node.operand, infix) + is UnaryPlusSyntax -> perform(node.operand, infix) + is UnaryMinusSyntax -> perform(node.operand, infix) + is RadicalSyntax -> perform(node.operand, infix) + is ExponentSyntax -> perform(node.operand, infix) is SuperscriptSyntax -> { - perform0(node.left, true) - perform0(node.right, true) + perform(node.left, true) + perform(node.right, true) } is SubscriptSyntax -> { - perform0(node.left, true) - perform0(node.right, true) + perform(node.left, true) + perform(node.right, true) } is BinaryOperatorSyntax -> { - perform0(node.prefix, infix) - perform0(node.left, infix) - perform0(node.right, infix) + perform(node.prefix, infix) + perform(node.left, infix) + perform(node.right, infix) } is BinaryPlusSyntax -> { - perform0(node.left, infix) - perform0(node.right, infix) + perform(node.left, infix) + perform(node.right, infix) } is BinaryMinusSyntax -> { - perform0(node.left, infix) - perform0(node.right, infix) + perform(node.left, infix) + perform(node.right, infix) } is FractionSyntax -> { node.infix = infix - perform0(node.left, infix) - perform0(node.right, infix) + perform(node.left, infix) + perform(node.right, infix) } is RadicalWithIndexSyntax -> { - perform0(node.left, true) - perform0(node.right, true) + perform(node.left, true) + perform(node.right, true) } is MultiplicationSyntax -> { - perform0(node.left, infix) - perform0(node.right, infix) + perform(node.left, infix) + perform(node.right, infix) } } - public override fun perform(node: MathSyntax): Unit = perform0(node) + perform(node) } /** @@ -160,39 +163,37 @@ public object BetterFraction : FeaturedMathRendererWithPostProcess.PostProcessSt * @author Iaroslav Postovalov */ @UnstableKMathAPI -public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage { - private fun perform0(node: MathSyntax): Boolean { +public val BetterExponent: PostProcessPhase = PostProcessPhase { node -> + fun perform(node: MathSyntax): Boolean { return when (node) { is NumberSyntax -> false is SymbolSyntax -> false is OperatorNameSyntax -> false is SpecialSymbolSyntax -> false - is OperandSyntax -> perform0(node.operand) - is UnaryOperatorSyntax -> perform0(node.prefix) || perform0(node.operand) - is UnaryPlusSyntax -> perform0(node.operand) - is UnaryMinusSyntax -> perform0(node.operand) + is OperandSyntax -> perform(node.operand) + is UnaryOperatorSyntax -> perform(node.prefix) || perform(node.operand) + is UnaryPlusSyntax -> perform(node.operand) + is UnaryMinusSyntax -> perform(node.operand) is RadicalSyntax -> true is ExponentSyntax -> { - val r = perform0(node.operand) + val r = perform(node.operand) node.useOperatorForm = r r } is SuperscriptSyntax -> true is SubscriptSyntax -> true - is BinaryOperatorSyntax -> perform0(node.prefix) || perform0(node.left) || perform0(node.right) - is BinaryPlusSyntax -> perform0(node.left) || perform0(node.right) - is BinaryMinusSyntax -> perform0(node.left) || perform0(node.right) + is BinaryOperatorSyntax -> perform(node.prefix) || perform(node.left) || perform(node.right) + is BinaryPlusSyntax -> perform(node.left) || perform(node.right) + is BinaryMinusSyntax -> perform(node.left) || perform(node.right) is FractionSyntax -> true is RadicalWithIndexSyntax -> true - is MultiplicationSyntax -> perform0(node.left) || perform0(node.right) + is MultiplicationSyntax -> perform(node.left) || perform(node.right) } } - public override fun perform(node: MathSyntax) { - perform0(node) - } + perform(node) } /** @@ -203,7 +204,7 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt */ @UnstableKMathAPI public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) : - FeaturedMathRendererWithPostProcess.PostProcessStage { + PostProcessPhase { public override fun perform(node: MathSyntax): Unit = when (node) { is NumberSyntax -> Unit is SymbolSyntax -> Unit From 7feb87ff052b0a99b5790cf788814fbee46f08cc Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 19 Jun 2021 20:52:26 +0700 Subject: [PATCH 391/393] Refactor benchmark report writer --- build.gradle.kts | 4 +- buildSrc/build.gradle.kts | 5 +- .../benchmarks/addBenchmarkProperties.kt | 89 +++++++++---------- settings.gradle.kts | 2 +- 4 files changed, 47 insertions(+), 53 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9978281f2..93cd67d47 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,9 +10,7 @@ allprojects { maven("http://logicrunch.research.it.uu.se/maven") { isAllowInsecureProtocol = true } - maven("https://oss.sonatype.org/content/repositories/snapshots") { - - } + maven("https://oss.sonatype.org/content/repositories/snapshots") mavenCentral() } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 8ff1c4369..fe69b05c6 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -4,13 +4,14 @@ plugins { } repositories { - gradlePluginPortal() + maven("https://repo.kotlin.link") mavenCentral() + gradlePluginPortal() } dependencies { api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0") - api("ru.mipt.npm:gradle-tools:0.9.10") + api("ru.mipt.npm:gradle-tools:0.10.0") api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.3.1") } diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt index 31d952157..b55e1320e 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt @@ -5,8 +5,11 @@ package space.kscience.kmath.benchmarks +import kotlinx.benchmark.gradle.BenchmarksExtension import kotlinx.serialization.* +import kotlinx.serialization.json.* import org.gradle.api.Project +import ru.mipt.npm.gradle.KScienceReadmeExtension import java.time.* import java.time.format.* import java.time.temporal.ChronoField.* @@ -42,63 +45,55 @@ private fun noun(number: Number, singular: String, plural: String) = if (number. fun Project.addBenchmarkProperties() { val benchmarksProject = this rootProject.subprojects.forEach { p -> - p.extensions.findByType(ru.mipt.npm.gradle.KScienceReadmeExtension::class.java)?.run { - benchmarksProject.extensions.findByType(kotlinx.benchmark.gradle.BenchmarksExtension::class.java)?.configurations?.forEach { cfg -> - // TODO remove this hack when https://github.com/mipt-npm/gradle-tools/pull/15 is merged - @Suppress("UNCHECKED_CAST") - (javaClass.getDeclaredField("properties") - .also { - it.isAccessible = true - }[this] as MutableMap Any?>)["benchmark${cfg.name.replaceFirstChar(Char::uppercase)}"] = - { - val launches = benchmarksProject.buildDir.resolve("reports/benchmarks/${cfg.name}") + p.extensions.findByType(KScienceReadmeExtension::class.java)?.run { + benchmarksProject.extensions.findByType(BenchmarksExtension::class.java)?.configurations?.forEach { cfg -> + property("benchmark${cfg.name.replaceFirstChar(Char::uppercase)}") { + val launches = benchmarksProject.buildDir.resolve("reports/benchmarks/${cfg.name}") - val resDirectory = launches.listFiles()?.maxByOrNull { - LocalDateTime.parse(it.name, ISO_DATE_TIME).atZone(ZoneId.systemDefault()).toInstant() - } + val resDirectory = launches.listFiles()?.maxByOrNull { + LocalDateTime.parse(it.name, ISO_DATE_TIME).atZone(ZoneId.systemDefault()).toInstant() + } - if (resDirectory == null) { - "> **Can't find appropriate benchmark data. Try generating readme files after running benchmarks**." - } else { - val reports = - kotlinx.serialization.json.Json.decodeFromString>( - resDirectory.resolve("jvm.json").readText() - ) + if (resDirectory == null) { + "> **Can't find appropriate benchmark data. Try generating readme files after running benchmarks**." + } else { + val reports = + Json.decodeFromString>(resDirectory.resolve("jvm.json").readText()) - buildString { - appendLine("
") - appendLine("") - appendLine("Report for benchmark configuration ${cfg.name}") - appendLine("") - appendLine() - val first = reports.first() + buildString { + appendLine("
") + appendLine("") + appendLine("Report for benchmark configuration ${cfg.name}") + appendLine("") + appendLine() + val first = reports.first() - appendLine("* Run on ${first.vmName} (build ${first.vmVersion}) with Java process:") - appendLine() - appendLine("```") - appendLine("${first.jvm} ${ - first.jvmArgs.joinToString(" ") - }") - appendLine("```") + appendLine("* Run on ${first.vmName} (build ${first.vmVersion}) with Java process:") + appendLine() + appendLine("```") + appendLine("${first.jvm} ${ + first.jvmArgs.joinToString(" ") + }") + appendLine("```") - appendLine("* JMH ${first.jmhVersion} was used in `${first.mode}` mode with ${first.warmupIterations} warmup ${ - noun(first.warmupIterations, "iteration", "iterations") - } by ${first.warmupTime} and ${first.measurementIterations} measurement ${ - noun(first.measurementIterations, "iteration", "iterations") - } by ${first.measurementTime}.") + appendLine("* JMH ${first.jmhVersion} was used in `${first.mode}` mode with ${first.warmupIterations} warmup ${ + noun(first.warmupIterations, "iteration", "iterations") + } by ${first.warmupTime} and ${first.measurementIterations} measurement ${ + noun(first.measurementIterations, "iteration", "iterations") + } by ${first.measurementTime}.") - appendLine() - appendLine("| Benchmark | Score |") - appendLine("|:---------:|:-----:|") + appendLine() + appendLine("| Benchmark | Score |") + appendLine("|:---------:|:-----:|") - reports.forEach { report -> - appendLine("|`${report.benchmark}`|${report.primaryMetric.score} ± ${report.primaryMetric.scoreError} ${report.primaryMetric.scoreUnit}|") - } - - appendLine("
") + reports.forEach { report -> + appendLine("|`${report.benchmark}`|${report.primaryMetric.score} ± ${report.primaryMetric.scoreError} ${report.primaryMetric.scoreUnit}|") } + + appendLine("
") } } + } } } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 710017588..063c69280 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,7 +5,7 @@ pluginManagement { gradlePluginPortal() } - val toolsVersion = "0.9.10" + val toolsVersion = "0.10.0" val kotlinVersion = "1.5.0" plugins { From 9f513b355c767c2c0536c5e4d7ad8df7dc6c2691 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sun, 20 Jun 2021 01:16:08 +0700 Subject: [PATCH 392/393] Update CMRandomGeneratorWrapper --- .../kmath/commons/random/CMRandomGeneratorWrapper.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt index 16a6967e2..4e2fbf980 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt @@ -5,7 +5,11 @@ package space.kscience.kmath.commons.random +import kotlinx.coroutines.runBlocking +import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator +import space.kscience.kmath.stat.next public class CMRandomGeneratorWrapper( public val factory: (IntArray) -> RandomGenerator, @@ -33,7 +37,10 @@ public class CMRandomGeneratorWrapper( public override fun nextInt(): Int = generator.nextInt() public override fun nextInt(n: Int): Int = generator.nextInt(n) - public override fun nextGaussian(): Double = TODO() + + @PerformancePitfall + public override fun nextGaussian(): Double = runBlocking { GaussianSampler(0.0, 1.0).next(generator) } + public override fun nextDouble(): Double = generator.nextDouble() public override fun nextLong(): Long = generator.nextLong() } From 83fc4e28d825343860c724f9a16fcf0b86f5f56b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Sat, 3 Jul 2021 17:11:47 +0700 Subject: [PATCH 393/393] Generate README, bump versions of Kotlin, Gradle, ND4J, ASM --- README.md | 4 ++-- benchmarks/build.gradle.kts | 2 +- build.gradle.kts | 8 ++++++-- gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- kmath-ast/README.md | 6 +++--- kmath-ast/build.gradle.kts | 3 +-- kmath-complex/README.md | 6 +++--- kmath-core/README.md | 6 +++--- kmath-ejml/README.md | 6 +++--- kmath-for-real/README.md | 6 +++--- kmath-functions/README.md | 6 +++--- kmath-jafama/README.md | 12 ++++++------ kmath-kotlingrad/README.md | 6 +++--- kmath-nd4j/README.md | 6 +++--- kmath-nd4j/build.gradle.kts | 5 ++--- kmath-tensors/README.md | 6 +++--- settings.gradle.kts | 5 ++--- 19 files changed, 49 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 015988cd3..7645256d9 100644 --- a/README.md +++ b/README.md @@ -309,8 +309,8 @@ repositories { } dependencies { - api("space.kscience:kmath-core:0.3.0-dev-13") - // api("space.kscience:kmath-core-jvm:0.3.0-dev-13") for jvm-specific version + api("space.kscience:kmath-core:0.3.0-dev-14") + // api("space.kscience:kmath-core-jvm:0.3.0-dev-14") for jvm-specific version } ``` diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 2198ac5d6..d96c5a8b6 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -47,7 +47,7 @@ kotlin { implementation(project(":kmath-nd4j")) implementation(project(":kmath-kotlingrad")) implementation(project(":kmath-viktor")) - implementation("org.nd4j:nd4j-native:1.0.0-beta7") + implementation("org.nd4j:nd4j-native:1.0.0-M1") // uncomment if your system supports AVX2 // val os = System.getProperty("os.name") // diff --git a/build.gradle.kts b/build.gradle.kts index 93cd67d47..d0f6ced78 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,12 +28,16 @@ subprojects { dokkaSourceSets.all { val readmeFile = File(this@subprojects.projectDir, "README.md") if (readmeFile.exists()) includes.from(readmeFile.absolutePath) - externalDocumentationLink("http://ejml.org/javadoc/") + externalDocumentationLink("https://ejml.org/javadoc/") externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/") externalDocumentationLink("https://deeplearning4j.org/api/latest/") externalDocumentationLink("https://axelclk.bitbucket.io/symja/javadoc/") externalDocumentationLink("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/") - externalDocumentationLink("https://breandan.net/kotlingrad/kotlingrad/", "https://breandan.net/kotlingrad/kotlingrad/kotlingrad/package-list") + + externalDocumentationLink( + "https://breandan.net/kotlingrad/kotlingrad/", + "https://breandan.net/kotlingrad/kotlingrad/kotlingrad/package-list", + ) } } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 18435 zcmY&<19zBR)MXm8v2EM7ZQHi-#I|kQZfv7Tn#Q)%81v4zX3d)U4d4 zYYc!v@NU%|U;_sM`2z(4BAilWijmR>4U^KdN)D8%@2KLcqkTDW%^3U(Wg>{qkAF z&RcYr;D1I5aD(N-PnqoEeBN~JyXiT(+@b`4Pv`;KmkBXYN48@0;iXuq6!ytn`vGp$ z6X4DQHMx^WlOek^bde&~cvEO@K$oJ}i`T`N;M|lX0mhmEH zuRpo!rS~#&rg}ajBdma$$}+vEhz?JAFUW|iZEcL%amAg_pzqul-B7Itq6Y_BGmOCC zX*Bw3rFz3R)DXpCVBkI!SoOHtYstv*e-May|+?b80ZRh$MZ$FerlC`)ZKt} zTd0Arf9N2dimjs>mg5&@sfTPsRXKXI;0L~&t+GH zkB<>wxI9D+k5VHHcB7Rku{Z>i3$&hgd9Mt_hS_GaGg0#2EHzyV=j=u5xSyV~F0*qs zW{k9}lFZ?H%@4hII_!bzao!S(J^^ZZVmG_;^qXkpJb7OyR*sPL>))Jx{K4xtO2xTr@St!@CJ=y3q2wY5F`77Tqwz8!&Q{f7Dp zifvzVV1!Dj*dxG%BsQyRP6${X+Tc$+XOG zzvq5xcC#&-iXlp$)L=9t{oD~bT~v^ZxQG;FRz|HcZj|^L#_(VNG)k{=_6|6Bs-tRNCn-XuaZ^*^hpZ@qwi`m|BxcF6IWc?_bhtK_cDZRTw#*bZ2`1@1HcB
`mLUmo_>@2R&nj7&CiH zF&laHkG~7#U>c}rn#H)q^|sk+lc!?6wg0xy`VPn!{4P=u@cs%-V{VisOxVqAR{XX+ zw}R;{Ux@6A_QPka=48|tph^^ZFjSHS1BV3xfrbY84^=?&gX=bmz(7C({=*oy|BEp+ zYgj;<`j)GzINJA>{HeSHC)bvp6ucoE`c+6#2KzY9)TClmtEB1^^Mk)(mXWYvup02e%Ghm9qyjz#fO3bNGBX} zFiB>dvc1+If!>I10;qZk`?6pEd*(?bI&G*3YLt;MWw&!?=Mf7%^Op?qnyXWur- zwX|S^P>jF?{m9c&mmK-epCRg#WB+-VDe!2d2~YVoi%7_q(dyC{(}zB${!ElKB2D}P z7QNFM!*O^?FrPMGZ}wQ0TrQAVqZy!weLhu_Zq&`rlD39r*9&2sJHE(JT0EY5<}~x@ z1>P0!L2IFDqAB!($H9s2fI`&J_c+5QT|b#%99HA3@zUWOuYh(~7q7!Pf_U3u!ij5R zjFzeZta^~RvAmd_TY+RU@e}wQaB_PNZI26zmtzT4iGJg9U(Wrgrl>J%Z3MKHOWV(? zj>~Ph$<~8Q_sI+)$DOP^9FE6WhO09EZJ?1W|KidtEjzBX3RCLUwmj9qH1CM=^}MaK z59kGxRRfH(n|0*lkE?`Rpn6d^u5J6wPfi0WF(rucTv(I;`aW)3;nY=J=igkjsn?ED ztH&ji>}TW8)o!Jg@9Z}=i2-;o4#xUksQHu}XT~yRny|kg-$Pqeq!^78xAz2mYP9+4 z9gwAoti2ICvUWxE&RZ~}E)#M8*zy1iwz zHqN%q;u+f6Ti|SzILm0s-)=4)>eb5o-0K zbMW8ecB4p^6OuIX@u`f{>Yn~m9PINEl#+t*jqalwxIx=TeGB9(b6jA}9VOHnE$9sC zH`;epyH!k-3kNk2XWXW!K`L_G!%xOqk0ljPCMjK&VweAxEaZ==cT#;!7)X&C|X{dY^IY(e4D#!tx^vV3NZqK~--JW~wtXJ8X19adXim?PdN(|@o(OdgH3AiHts~?#QkolO?*=U_buYC&tQ3sc(O5HGHN~=6wB@dgIAVT$ z_OJWJ^&*40Pw&%y^t8-Wn4@l9gOl`uU z{Uda_uk9!Iix?KBu9CYwW9Rs=yt_lE11A+k$+)pkY5pXpocxIEJe|pTxwFgB%Kpr&tH;PzgOQ&m|(#Otm?@H^r`v)9yiR8v&Uy>d#TNdRfyN4Jk;`g zp+jr5@L2A7TS4=G-#O<`A9o;{En5!I8lVUG?!PMsv~{E_yP%QqqTxxG%8%KxZ{uwS zOT+EA5`*moN8wwV`Z=wp<3?~f#frmID^K?t7YL`G^(X43gWbo!6(q*u%HxWh$$^2EOq`Hj zp=-fS#Av+s9r-M)wGIggQ)b<@-BR`R8l1G@2+KODmn<_$Tzb7k35?e8;!V0G>`(!~ zY~qZz!6*&|TupOcnvsQYPbcMiJ!J{RyfezB^;fceBk znpA1XS)~KcC%0^_;ihibczSxwBuy;^ksH7lwfq7*GU;TLt*WmUEVQxt{ zKSfJf;lk$0XO8~48Xn2dnh8tMC9WHu`%DZj&a`2!tNB`5%;Md zBs|#T0Ktf?vkWQ)Y+q!At1qgL`C|nbzvgc(+28Q|4N6Geq)Il%+I5c@t02{9^=QJ?=h2BTe`~BEu=_u3xX2&?^zwcQWL+)7dI>JK0g8_`W1n~ zMaEP97X>Ok#=G*nkPmY`VoP8_{~+Rp7DtdSyWxI~?TZHxJ&=6KffcO2Qx1?j7=LZA z?GQt`oD9QpXw+s7`t+eeLO$cpQpl9(6h3_l9a6OUpbwBasCeCw^UB6we!&h9Ik@1zvJ`j4i=tvG9X8o34+N|y(ay~ho$f=l z514~mP>Z>#6+UxM<6@4z*|hFJ?KnkQBs_9{H(-v!_#Vm6Z4(xV5WgWMd3mB9A(>@XE292#k(HdI7P zJkQ2)`bQXTKlr}{VrhSF5rK9TsjtGs0Rs&nUMcH@$ZX_`Hh$Uje*)(Wd&oLW($hZQ z_tPt`{O@f8hZ<}?aQc6~|9iHt>=!%We3=F9yIfiqhXqp=QUVa!@UY@IF5^dr5H8$R zIh{=%S{$BHG+>~a=vQ={!B9B=<-ID=nyjfA0V8->gN{jRL>Qc4Rc<86;~aY+R!~Vs zV7MI~gVzGIY`B*Tt@rZk#Lg}H8sL39OE31wr_Bm%mn}8n773R&N)8B;l+-eOD@N$l zh&~Wz`m1qavVdxwtZLACS(U{rAa0;}KzPq9r76xL?c{&GaG5hX_NK!?)iq`t7q*F# zFoKI{h{*8lb>&sOeHXoAiqm*vV6?C~5U%tXR8^XQ9Y|(XQvcz*>a?%HQ(Vy<2UhNf zVmGeOO#v159KV@1g`m%gJ)XGPLa`a|?9HSzSSX{j;)xg>G(Ncc7+C>AyAWYa(k}5B3mtzg4tsA=C^Wfezb1&LlyrBE1~kNfeiubLls{C)!<%#m@f}v^o+7<VZ6!FZ;JeiAG@5vw7Li{flC8q1%jD_WP2ApBI{fQ}kN zhvhmdZ0bb5(qK@VS5-)G+@GK(tuF6eJuuV5>)Odgmt?i_`tB69DWpC~e8gqh!>jr_ zL1~L0xw@CbMSTmQflpRyjif*Y*O-IVQ_OFhUw-zhPrXXW>6X}+73IoMsu2?uuK3lT>;W#38#qG5tDl66A7Y{mYh=jK8Se!+f=N7%nv zYSHr6a~Nxd`jqov9VgII{%EpC_jFCEc>>SND0;}*Ja8Kv;G)MK7?T~h((c&FEBcQq zvUU1hW2^TX(dDCeU@~a1LF-(+#lz3997A@pipD53&Dr@III2tlw>=!iGabjXzbyUJ z4Hi~M1KCT-5!NR#I%!2Q*A>mqI{dpmUa_mW)%SDs{Iw1LG}0y=wbj@0ba-`q=0!`5 zr(9q1p{#;Rv2CY!L#uTbs(UHVR5+hB@m*zEf4jNu3(Kj$WwW|v?YL*F_0x)GtQC~! zzrnZRmBmwt+i@uXnk05>uR5&1Ddsx1*WwMrIbPD3yU*2By`71pk@gt{|H0D<#B7&8 z2dVmXp*;B)SWY)U1VSNs4ds!yBAj;P=xtatUx^7_gC5tHsF#vvdV;NmKwmNa1GNWZ zi_Jn-B4GnJ%xcYWD5h$*z^haku#_Irh818x^KB)3-;ufjf)D0TE#6>|zFf@~pU;Rs zNw+}c9S+6aPzxkEA6R%s*xhJ37wmgc)-{Zd1&mD5QT}4BQvczWr-Xim>(P^)52`@R z9+Z}44203T5}`AM_G^Snp<_KKc!OrA(5h7{MT^$ZeDsSr(R@^kI?O;}QF)OU zQ9-`t^ys=6DzgLcWt0U{Q(FBs22=r zKD%fLQ^5ZF24c-Z)J{xv?x$&4VhO^mswyb4QTIofCvzq+27*WlYm;h@;Bq%i;{hZA zM97mHI6pP}XFo|^pRTuWQzQs3B-8kY@ajLV!Fb?OYAO3jFv*W-_;AXd;G!CbpZt04iW`Ie^_+cQZGY_Zd@P<*J9EdRsc>c=edf$K|;voXRJ zk*aC@@=MKwR120(%I_HX`3pJ+8GMeO>%30t?~uXT0O-Tu-S{JA;zHoSyXs?Z;fy58 zi>sFtI7hoxNAdOt#3#AWFDW)4EPr4kDYq^`s%JkuO7^efX+u#-qZ56aoRM!tC^P6O zP(cFuBnQGjhX(^LJ(^rVe4-_Vk*3PkBCj!?SsULdmVr0cGJM^=?8b0^DuOFq>0*yA zk1g|C7n%pMS0A8@Aintd$fvRbH?SNdRaFrfoAJ=NoX)G5Gr}3-$^IGF+eI&t{I-GT zp=1fj)2|*ur1Td)+s&w%p#E6tDXX3YYOC{HGHLiCvv?!%%3DO$B$>A}aC;8D0Ef#b z{7NNqC8j+%1n95zq8|hFY`afAB4E)w_&7?oqG0IPJZv)lr{MT}>9p?}Y`=n+^CZ6E zKkjIXPub5!82(B-O2xQojW^P(#Q*;ETpEr^+Wa=qDJ9_k=Wm@fZB6?b(u?LUzX(}+ zE6OyapdG$HC& z&;oa*ALoyIxVvB2cm_N&h&{3ZTuU|aBrJlGOLtZc3KDx)<{ z27@)~GtQF@%6B@w3emrGe?Cv_{iC@a#YO8~OyGRIvp@%RRKC?fclXMP*6GzBFO z5U4QK?~>AR>?KF@I;|(rx(rKxdT9-k-anYS+#S#e1SzKPslK!Z&r8iomPsWG#>`Ld zJ<#+8GFHE!^wsXt(s=CGfVz5K+FHYP5T0E*?0A-z*lNBf)${Y`>Gwc@?j5{Q|6;Bl zkHG1%r$r&O!N^><8AEL+=y(P$7E6hd=>BZ4ZZ9ukJ2*~HR4KGvUR~MUOe$d>E5UK3 z*~O2LK4AnED}4t1Fs$JgvPa*O+WeCji_cn1@Tv7XQ6l@($F1K%{E$!naeX)`bfCG> z8iD<%_M6aeD?a-(Qqu61&fzQqC(E8ksa%CulMnPvR35d{<`VsmaHyzF+B zF6a@1$CT0xGVjofcct4SyxA40uQ`b#9kI)& z?B67-12X-$v#Im4CVUGZHXvPWwuspJ610ITG*A4xMoRVXJl5xbk;OL(;}=+$9?H`b z>u2~yd~gFZ*V}-Q0K6E@p}mtsri&%Zep?ZrPJmv`Qo1>94Lo||Yl)nqwHXEbe)!g( zo`w|LU@H14VvmBjjkl~=(?b{w^G$~q_G(HL`>|aQR%}A64mv0xGHa`S8!*Wb*eB}` zZh)&rkjLK!Rqar)UH)fM<&h&@v*YyOr!Xk2OOMV%$S2mCRdJxKO1RL7xP_Assw)bb z9$sQ30bapFfYTS`i1PihJZYA#0AWNmp>x(;C!?}kZG7Aq?zp!B+gGyJ^FrXQ0E<>2 zCjqZ(wDs-$#pVYP3NGA=en<@_uz!FjFvn1&w1_Igvqs_sL>ExMbcGx4X5f%`Wrri@ z{&vDs)V!rd=pS?G(ricfwPSg(w<8P_6=Qj`qBC7_XNE}1_5>+GBjpURPmvTNE7)~r)Y>ZZecMS7Ro2` z0}nC_GYo3O7j|Wux?6-LFZs%1IV0H`f`l9or-8y0=5VGzjPqO2cd$RRHJIY06Cnh- ztg@Pn1OeY=W`1Mv3`Ti6!@QIT{qcC*&vptnX4Pt1O|dWv8u2s|(CkV`)vBjAC_U5` zCw1f&c4o;LbBSp0=*q z3Y^horBAnR)u=3t?!}e}14%K>^562K!)Vy6r~v({5{t#iRh8WIL|U9H6H97qX09xp zjb0IJ^9Lqxop<-P*VA0By@In*5dq8Pr3bTPu|ArID*4tWM7w+mjit0PgmwLV4&2PW z3MnIzbdR`3tPqtUICEuAH^MR$K_u8~-U2=N1)R=l>zhygus44>6V^6nJFbW-`^)f} zI&h$FK)Mo*x?2`0npTD~jRd}5G~-h8=wL#Y-G+a^C?d>OzsVl7BFAaM==(H zR;ARWa^C3J)`p~_&FRsxt|@e+M&!84`eq)@aO9yBj8iifJv0xVW4F&N-(#E=k`AwJ z3EFXWcpsRlB%l_0Vdu`0G(11F7( zsl~*@XP{jS@?M#ec~%Pr~h z2`M*lIQaolzWN&;hkR2*<=!ORL(>YUMxOzj(60rQfr#wTrkLO!t{h~qg% zv$R}0IqVIg1v|YRu9w7RN&Uh7z$ijV=3U_M(sa`ZF=SIg$uY|=NdC-@%HtkUSEqJv zg|c}mKTCM=Z8YmsFQu7k{VrXtL^!Cts-eb@*v0B3M#3A7JE*)MeW1cfFqz~^S6OXFOIP&iL;Vpy z4dWKsw_1Wn%Y;eW1YOfeP_r1s4*p1C(iDG_hrr~-I%kA>ErxnMWRYu{IcG{sAW;*t z9T|i4bI*g)FXPpKM@~!@a7LDVVGqF}C@mePD$ai|I>73B+9!Ks7W$pw;$W1B%-rb; zJ*-q&ljb=&41dJ^*A0)7>Wa@khGZ;q1fL(2qW=|38j43mTl_;`PEEw07VKY%71l6p z@F|jp88XEnm1p~<5c*cVXvKlj0{THF=n3sU7g>Ki&(ErR;!KSmfH=?49R5(|c_*xw z4$jhCJ1gWT6-g5EV)Ahg?Nw=}`iCyQ6@0DqUb%AZEM^C#?B-@Hmw?LhJ^^VU>&phJ zlB!n5&>I>@sndh~v$2I2Ue23F?0!0}+9H~jg7E`?CS_ERu75^jSwm%!FTAegT`6s7 z^$|%sj2?8wtPQR>@D3sA0-M-g-vL@47YCnxdvd|1mPymvk!j5W1jHnVB&F-0R5e-vs`@u8a5GKdv`LF7uCfKncI4+??Z4iG@AxuX7 z6+@nP^TZ5HX#*z(!y+-KJ3+Ku0M90BTY{SC^{ z&y2#RZPjfX_PE<<>XwGp;g4&wcXsQ0T&XTi(^f+}4qSFH1%^GYi+!rJo~t#ChTeAX zmR0w(iODzQOL+b&{1OqTh*psAb;wT*drr^LKdN?c?HJ*gJl+%kEH&48&S{s28P=%p z7*?(xFW_RYxJxxILS!kdLIJYu@p#mnQ(?moGD1)AxQd66X6b*KN?o&e`u9#N4wu8% z^Gw#G!@|>c740RXziOR=tdbkqf(v~wS_N^CS^1hN-N4{Dww1lvSWcBTX*&9}Cz|s@ z*{O@jZ4RVHq19(HC9xSBZI0M)E;daza+Q*zayrX~N5H4xJ33BD4gn5Ka^Hj{995z4 zzm#Eo?ntC$q1a?)dD$qaC_M{NW!5R!vVZ(XQqS67xR3KP?rA1^+s3M$60WRTVHeTH z6BJO$_jVx0EGPXy}XK_&x597 zt(o6ArN8vZX0?~(lFGHRtHP{gO0y^$iU6Xt2e&v&ugLxfsl;GD)nf~3R^ACqSFLQ< zV7`cXgry((wDMJB55a6D4J;13$z6pupC{-F+wpToW%k1qKjUS^$Mo zN3@}T!ZdpiV7rkNvqP3KbpEn|9aB;@V;gMS1iSb@ zwyD7!5mfj)q+4jE1dq3H`sEKgrVqk|y8{_vmn8bMOi873!rmnu5S=1=-DFx+Oj)Hi zx?~ToiJqOrvSou?RVALltvMADodC7BOg7pOyc4m&6yd(qIuV5?dYUpYzpTe!BuWKi zpTg(JHBYzO&X1e{5o|ZVU-X5e?<}mh=|eMY{ldm>V3NsOGwyxO2h)l#)rH@BI*TN; z`yW26bMSp=k6C4Ja{xB}s`dNp zE+41IwEwo>7*PA|7v-F#jLN>h#a`Er9_86!fwPl{6yWR|fh?c%qc44uP~Ocm2V*(* zICMpS*&aJjxutxKC0Tm8+FBz;3;R^=ajXQUB*nTN*Lb;mruQHUE<&=I7pZ@F-O*VMkJbI#FOrBM8`QEL5Uy=q5e2 z_BwVH%c0^uIWO0*_qD;0jlPoA@sI7BPwOr-mrp7y`|EF)j;$GYdOtEPFRAKyUuUZS z(N4)*6R*ux8s@pMdC*TP?Hx`Zh{{Ser;clg&}CXriXZCr2A!wIoh;j=_eq3_%n7V} za?{KhXg2cXPpKHc90t6=`>s@QF-DNcTJRvLTS)E2FTb+og(wTV7?$kI?QZYgVBn)& zdpJf@tZ{j>B;<MVHiPl_U&KlqBT)$ic+M0uUQWK|N1 zCMl~@o|}!!7yyT%7p#G4?T^Azxt=D(KP{tyx^lD_(q&|zNFgO%!i%7T`>mUuU^FeR zHP&uClWgXm6iXgI8*DEA!O&X#X(zdrNctF{T#pyax16EZ5Lt5Z=RtAja!x+0Z31U8 zjfaky?W)wzd+66$L>o`n;DISQNs09g{GAv%8q2k>2n8q)O^M}=5r#^WR^=se#WSCt zQ`7E1w4qdChz4r@v6hgR?nsaE7pg2B6~+i5 zcTTbBQ2ghUbC-PV(@xvIR(a>Kh?{%YAsMV#4gt1nxBF?$FZ2~nFLKMS!aK=(`WllA zHS<_7ugqKw!#0aUtQwd#A$8|kPN3Af?Tkn)dHF?_?r#X68Wj;|$aw)Wj2Dkw{6)*^ zZfy!TWwh=%g~ECDCy1s8tTgWCi}F1BvTJ9p3H6IFq&zn#3FjZoecA_L_bxGWgeQup zAAs~1IPCnI@H>g|6Lp^Bk)mjrA3_qD4(D(65}l=2RzF-8@h>|Aq!2K-qxt(Q9w7c^ z;gtx`I+=gKOl;h=#fzSgw-V*YT~2_nnSz|!9hIxFb{~dKB!{H zSi??dnmr@%(1w^Be=*Jz5bZeofEKKN&@@uHUMFr-DHS!pb1I&;x9*${bmg6=2I4Zt zHb5LSvojY7ubCNGhp)=95jQ00sMAC{IZdAFsN!lAVQDeiec^HAu=8);2AKqNTT!&E zo+FAR`!A1#T6w@0A+o%&*yzkvxsrqbrfVTG+@z8l4+mRi@j<&)U9n6L>uZoezW>qS zA4YfO;_9dQSyEYpkWnsk0IY}Nr2m(ql@KuQjLgY-@g z4=$uai6^)A5+~^TvLdvhgfd+y?@+tRE^AJabamheJFnpA#O*5_B%s=t8<;?I;qJ}j z&g-9?hbwWEez-!GIhqpB>nFvyi{>Yv>dPU=)qXnr;3v-cd`l}BV?6!v{|cHDOx@IG z;TSiQQ(8=vlH^rCEaZ@Yw}?4#a_Qvx=}BJuxACxm(E7tP4hki^jU@8A zUS|4tTLd)gr@T|F$1eQXPY%fXb7u}(>&9gsd3It^B{W#6F2_g40cgo1^)@-xO&R5X z>qKon+Nvp!4v?-rGQu#M_J2v+3e+?N-WbgPQWf`ZL{Xd9KO^s{uIHTJ6~@d=mc7i z+##ya1p+ZHELmi%3C>g5V#yZt*jMv( zc{m*Y;7v*sjVZ-3mBuaT{$g+^sbs8Rp7BU%Ypi+c%JxtC4O}|9pkF-p-}F{Z7-+45 zDaJQx&CNR)8x~0Yf&M|-1rw%KW3ScjWmKH%J1fBxUp(;F%E+w!U470e_3%+U_q7~P zJm9VSWmZ->K`NfswW(|~fGdMQ!K2z%k-XS?Bh`zrjZDyBMu74Fb4q^A=j6+Vg@{Wc zPRd5Vy*-RS4p1OE-&8f^Fo}^yDj$rb+^>``iDy%t)^pHSV=En5B5~*|32#VkH6S%9 zxgIbsG+|{-$v7mhOww#v-ejaS>u(9KV9_*X!AY#N*LXIxor9hDv%aie@+??X6@Et=xz>6ev9U>6Pn$g4^!}w2Z%Kpqpp+M%mk~?GE-jL&0xLC zy(`*|&gm#mLeoRU8IU?Ujsv=;ab*URmsCl+r?%xcS1BVF*rP}XRR%MO_C!a9J^fOe>U;Y&3aj3 zX`3?i12*^W_|D@VEYR;h&b^s#Kd;JMNbZ#*x8*ZXm(jgw3!jyeHo14Zq!@_Q`V;Dv zKik~!-&%xx`F|l^z2A92aCt4x*I|_oMH9oeqsQgQDgI0j2p!W@BOtCTK8Jp#txi}7 z9kz);EX-2~XmxF5kyAa@n_$YYP^Hd4UPQ>O0-U^-pw1*n{*kdX`Jhz6{!W=V8a$0S z9mYboj#o)!d$gs6vf8I$OVOdZu7L5%)Vo0NhN`SwrQFhP3y4iXe2uV@(G{N{yjNG( zKvcN{k@pXkxyB~9ucR(uPSZ7{~sC=lQtz&V(^A^HppuN!@B4 zS>B=kb14>M-sR>{`teApuHlca6YXs6&sRvRV;9G!XI08CHS~M$=%T~g5Xt~$exVk` zWP^*0h{W%`>K{BktGr@+?ZP}2t0&smjKEVw@3=!rSjw5$gzlx`{dEajg$A58m|Okx zG8@BTPODSk@iqLbS*6>FdVqk}KKHuAHb0UJNnPm!(XO{zg--&@#!niF4T!dGVdNif z3_&r^3+rfQuV^8}2U?bkI5Ng*;&G>(O4&M<86GNxZK{IgKNbRfpg>+32I>(h`T&uv zUN{PRP&onFj$tn1+Yh|0AF330en{b~R+#i9^QIbl9fBv>pN|k&IL2W~j7xbkPyTL^ z*TFONZUS2f33w3)fdzr?)Yg;(s|||=aWZV(nkDaACGSxNCF>XLJSZ=W@?$*` z#sUftY&KqTV+l@2AP5$P-k^N`Bme-xcWPS|5O~arUq~%(z8z87JFB|llS&h>a>Som zC34(_uDViE!H2jI3<@d+F)LYhY)hoW6)i=9u~lM*WH?hI(yA$X#ip}yYld3RAv#1+sBt<)V_9c4(SN9Fn#$}_F}A-}P>N+8io}I3mh!}> z*~*N}ZF4Zergb;`R_g49>ZtTCaEsCHiFb(V{9c@X0`YV2O^@c6~LXg2AE zhA=a~!ALnP6aO9XOC^X15(1T)3!1lNXBEVj5s*G|Wm4YBPV`EOhU&)tTI9-KoLI-U zFI@adu6{w$dvT(zu*#aW*4F=i=!7`P!?hZy(9iL;Z^De3?AW`-gYTPALhrZ*K2|3_ zfz;6xQN9?|;#_U=4t^uS2VkQ8$|?Ub5CgKOj#Ni5j|(zX>x#K(h7LgDP-QHwok~-I zOu9rn%y97qrtKdG=ep)4MKF=TY9^n6CugQ3#G2yx;{))hvlxZGE~rzZ$qEHy-8?pU#G;bwufgSN6?*BeA!7N3RZEh{xS>>-G1!C(e1^ zzd#;39~PE_wFX3Tv;zo>5cc=md{Q}(Rb?37{;YPtAUGZo7j*yHfGH|TOVR#4ACaM2 z;1R0hO(Gl}+0gm9Bo}e@lW)J2OU4nukOTVKshHy7u)tLH^9@QI-jAnDBp(|J8&{fKu=_97$v&F67Z zq+QsJ=gUx3_h_%=+q47msQ*Ub=gMzoSa@S2>`Y9Cj*@Op4plTc!jDhu51nSGI z^sfZ(4=yzlR}kP2rcHRzAY9@T7f`z>fdCU0zibx^gVg&fMkcl)-0bRyWe12bT0}<@ z^h(RgGqS|1y#M;mER;8!CVmX!j=rfNa6>#_^j{^C+SxGhbSJ_a0O|ae!ZxiQCN2qA zKs_Z#Zy|9BOw6x{0*APNm$6tYVG2F$K~JNZ!6>}gJ_NLRYhcIsxY1z~)mt#Yl0pvC zO8#Nod;iow5{B*rUn(0WnN_~~M4|guwfkT(xv;z)olmj=f=aH#Y|#f_*d1H!o( z!EXNxKxth9w1oRr0+1laQceWfgi8z`YS#uzg#s9-QlTT7y2O^^M1PZx z3YS7iegfp6Cs0-ixlG93(JW4wuE7)mfihw}G~Uue{Xb+#F!BkDWs#*cHX^%(We}3% zT%^;m&Juw{hLp^6eyM}J({luCL_$7iRFA6^8B!v|B9P{$42F>|M`4Z_yA{kK()WcM zu#xAZWG%QtiANfX?@+QQOtbU;Avr*_>Yu0C2>=u}zhH9VLp6M>fS&yp*-7}yo8ZWB z{h>ce@HgV?^HgwRThCYnHt{Py0MS=Ja{nIj5%z;0S@?nGQ`z`*EVs&WWNwbzlk`(t zxDSc)$dD+4G6N(p?K>iEKXIk>GlGKTH{08WvrehnHhh%tgpp&8db4*FLN zETA@<$V=I7S^_KxvYv$Em4S{gO>(J#(Wf;Y%(NeECoG3n+o;d~Bjme-4dldKukd`S zRVAnKxOGjWc;L#OL{*BDEA8T=zL8^`J=2N)d&E#?OMUqk&9j_`GX*A9?V-G zdA5QQ#(_Eb^+wDkDiZ6RXL`fck|rVy%)BVv;dvY#`msZ}{x5fmd! zInmWSxvRgXbJ{unxAi*7=Lt&7_e0B#8M5a=Ad0yX#0rvMacnKnXgh>4iiRq<&wit93n!&p zeq~-o37qf)L{KJo3!{l9l9AQb;&>)^-QO4RhG>j`rBlJ09~cbfNMR_~pJD1$UzcGp zOEGTzz01j$=-kLC+O$r8B|VzBotz}sj(rUGOa7PDYwX~9Tum^sW^xjjoncxSz;kqz z$Pz$Ze|sBCTjk7oM&`b5g2mFtuTx>xl{dj*U$L%y-xeQL~|i>KzdUHeep-Yd@}p&L*ig< zgg__3l9T=nbM3bw0Sq&Z2*FA)P~sx0h634BXz0AxV69cED7QGTbK3?P?MENkiy-mV zZ1xV5ry3zIpy>xmThBL0Q!g+Wz@#?6fYvzmEczs(rcujrfCN=^!iWQ6$EM zaCnRThqt~gI-&6v@KZ78unqgv9j6-%TOxpbV`tK{KaoBbhc}$h+rK)5h|bT6wY*t6st-4$e99+Egb#3ip+ERbve08G@Ref&hP)qB&?>B94?eq5i3k;dOuU#!y-@+&5>~!FZik=z4&4|YHy=~!F254 zQAOTZr26}Nc7jzgJ;V~+9ry#?7Z0o*;|Q)k+@a^87lC}}1C)S))f5tk+lMNqw>vh( z`A9E~5m#b9!ZDBltf7QIuMh+VheCoD7nCFhuzThlhA?|8NCt3w?oWW|NDin&&eDU6 zwH`aY=))lpWG?{fda=-auXYp1WIPu&3 zwK|t(Qiqvc@<;1_W#ALDJ}bR;3&v4$9rP)eAg`-~iCte`O^MY+SaP!w%~+{{1tMo` zbp?T%ENs|mHP)Lsxno=nWL&qizR+!Ib=9i%4=B@(Umf$|7!WVxkD%hfRjvxV`Co<; zG*g4QG_>;RE{3V_DOblu$GYm&!+}%>G*yO{-|V9GYG|bH2JIU2iO}ZvY>}Fl%1!OE zZFsirH^$G>BDIy`8;R?lZl|uu@qWj2T5}((RG``6*05AWsVVa2Iu>!F5U>~7_Tlv{ zt=Dpgm~0QVa5mxta+fUt)I0gToeEm9eJX{yYZ~3sLR&nCuyuFWuiDIVJ+-lwViO(E zH+@Rg$&GLueMR$*K8kOl>+aF84Hss5p+dZ8hbW$=bWNIk0paB!qEK$xIm5{*^ad&( zgtA&gb&6FwaaR2G&+L+Pp>t^LrG*-B&Hv;-s(h0QTuYWdnUObu8LRSZoAVd7SJ;%$ zh%V?58mD~3G2X<$H7I)@x?lmbeeSY7X~QiE`dfQ5&K^FB#9e!6!@d9vrSt!);@ZQZ zO#84N5yH$kjm9X4iY#f+U`FKhg=x*FiDoUeu1O5LcC2w&$~5hKB9ZnH+8BpbTGh5T zi_nfmyQY$vQh%ildbR7T;7TKPxSs#vhKR|uup`qi1PufMa(tNCjRbllakshQgn1)a8OO-j8W&aBc_#q1hKDF5-X$h`!CeT z+c#Ial~fDsGAenv7~f@!icm(~)a3OKi((=^zcOb^qH$#DVciGXslUwTd$gt{7)&#a`&Lp ze%AnL0#U?lAl8vUkv$n>bxH*`qOujO0HZkPWZnE0;}0DSEu1O!hg-d9#{&#B1Dm)L zvN%r^hdEt1vR<4zwshg*0_BNrDWjo65be1&_82SW8#iKWs7>TCjUT;-K~*NxpG2P% zovXUo@S|fMGudVSRQrP}J3-Wxq;4xIxJJC|Y#TQBr>pwfy*%=`EUNE*dr-Y?9y9xK zmh1zS@z{^|UL}v**LNYY!?1qIRPTvr!gNXzE{%=-`oKclPrfMKwn` zUwPeIvLcxkIV>(SZ-SeBo-yw~{p!<&_}eELG?wxp zee-V59%@BtB+Z&Xs=O(@P$}v_qy1m=+`!~r^aT> zY+l?+6(L-=P%m4ScfAYR8;f9dyVw)@(;v{|nO#lAPI1xDHXMYt~-BGiP&9y2OQsYdh7-Q1(vL<$u6W0nxVn-qh=nwuRk}{d!uACozccRGx6~xZQ;=#JCE?OuA@;4 zadp$sm}jfgW4?La(pb!3f0B=HUI{5A4b$2rsB|ZGb?3@CTA{|zBf07pYpQ$NM({C6Srv6%_{rVkCndT=1nS}qyEf}Wjtg$e{ng7Wgz$7itYy0sWW_$qld);iUm85GBH)fk3b=2|5mvflm?~inoVo zDH_%e;y`DzoNj|NgZ`U%a9(N*=~8!qqy0Etkxo#`r!!{|(NyT0;5= z8nVZ6AiM+SjMG8J@6c4_f-KXd_}{My?Se1GWP|@wROFpD^5_lu?I%CBzpwi(`x~xh B8dv}T delta 17845 zcmV)CK*GO}(F4QI1F(Jx4W$DjNjn4p0N4ir06~)x5+0MO2`GQvQyWzj|J`gh3(E#l zNGO!HfVMRRN~%`0q^)g%XlN*vP!O#;m*h5VyX@j-1N|HN;8S1vqEAj=eCdn`)tUB9 zXZjcT^`bL6qvL}gvXj%9vrOD+x!Gc_0{$Zg+6lTXG$bmoEBV z*%y^c-mV0~Rjzv%e6eVI)yl>h;TMG)Ft8lqpR`>&IL&`>KDi5l$AavcVh9g;CF0tY zw_S0eIzKD?Nj~e4raA8wxiiImTRzv6;b6|LFmw)!E4=CiJ4I%&axSey4zE-MIh@*! z*P;K2Mx{xVYPLeagKA}Hj=N=1VrWU`ukuBnc14iBG?B}Uj>?=2UMk4|42=()8KOnc zrJzAxxaEIfjw(CKV6F$35u=1qyf(%cY8fXaS9iS?yetY{mQ#Xyat*7sSoM9fJlZqq zyasQ3>D>6p^`ck^Y|kYYZB*G})uAbQ#7)Jeb~glGz@2rPu}zBWDzo5K$tP<|meKV% z{Swf^eq6NBioF)v&~9NLIxHMTKe6gJ@QQ^A6fA!n#u1C&n`aG7TDXKM1Jly-DwTB` z+6?=Y)}hj;C#r5>&x;MCM4U13nuXVK*}@yRY~W3X%>U>*CB2C^K6_OZsXD!nG2RSX zQg*0)$G3%Es$otA@p_1N!hIPT(iSE=8OPZG+t)oFyD~{nevj0gZen$p>U<7}uRE`t5Mk1f4M0K*5 zbn@3IG5I2mk;8K>*RZ zPV6iL006)S001s%0eYj)9hu1 z9o)iQT9(v*sAuZ|ot){RrZ0Qw4{E0A+!Yx_M~#Pj&OPUM&i$RU=Uxu}e*6Sr2ror= z&?lmvFCO$)BY+^+21E>ENWe`I0{02H<-lz&?})gIVFyMWxX0B|0b?S6?qghp3lDgz z2?0|ALJU=7s-~Lb3>9AA5`#UYCl!Xeh^i@bxs5f&SdiD!WN}CIgq&WI4VCW;M!UJL zX2};d^sVj5oVl)OrkapV-C&SrG)*x=X*ru!2s04TjZ`pY$jP)4+%)7&MlpiZ`lgoF zo_p>^4qGz^(Y*uB10dY2kcIbt=$FIdYNqk;~47wf@)6|nJp z1cocL3zDR9N2Pxkw)dpi&_rvMW&Dh0@T*_}(1JFSc0S~Ph2Sr=vy)u*=TY$i_IHSo zR+&dtWFNxHE*!miRJ%o5@~GK^G~4$LzEYR-(B-b(L*3jyTq}M3d0g6sdx!X3-m&O% zK5g`P179KHJKXpIAAX`A2MFUA;`nXx^b?mboVbQgigIHTU8FI>`q53AjWaD&aowtj z{XyIX>c)*nLO~-WZG~>I)4S1d2q@&?nwL)CVSWqWi&m1&#K1!gt`g%O4s$u^->Dwq ziKc&0O9KQ7000OG0000%03-m(e&Y`S09YWC4iYDSty&3q8^?8ij|8zxaCt!zCFq1@ z9TX4Hl68`nY>}cQNW4Ullqp$~SHO~l1!CdFLKK}ij_t^a?I?C^CvlvnZkwiVn>dl2 z2$V(JN{`5`-8ShF_ek6HNRPBlPuIPYu>TAeAV5O2)35r3*_k(Q-h1+h5pb(Zu%oJ__pBsW0n5ILw`!&QR&YV`g0Fe z(qDM!FX_7;`U3rxX#QHT{f%h;)Eursw=*#qvV)~y%^Uo^% zi-%sMe^uz;#Pe;@{JUu05zT*i=u7mU9{MkT`ft(vPdQZoK&2mg=tnf8FsaNQ+QcPg zB>vP8Rd6Z0JoH5_Q`zldg;hx4azQCq*rRZThqlqTRMzn1O3_rQTrHk8LQ<{5UYN~` zM6*~lOGHyAnx&#yCK{i@%N1Us@=6cw=UQxpSE;<(LnnES%6^q^QhBYQ-VCSmIu8wh z@_LmwcFDfAhIn>`%h7L{)iGBzu`Md4dj-m3C8mA9+BL*<>q z#$7^ttIBOE-=^|zmG`K8yUKT{yjLu2SGYsreN0*~9yhFxn4U};Nv1XXj1fH*v-g=3 z@tCPc`YdzQGLp%zXwo*o$m9j-+~nSWls#s|?PyrHO%SUGdk**X9_=|b)Y%^j_V$3S z>mL2A-V)Q}qb(uZipEFVm?}HWc+%G6_K+S+87g-&RkRQ8-{0APDil115eG|&>WQhU zufO*|e`hFks^cJJmx_qNx{ltSp3aT|XgD5-VxGGXb7gkiOG$w^qMVBDjR8%!Sbh72niHRDV* ziFy8LE+*$j?t^6aZP9qt-ow;hzkmhvy*Hn-X^6?yVMbtNbyqZQ^rXg58`gk+I%Wv} zn_)dRq+3xjc8D%}EQ%nnTF7L7m}o9&*^jf`_qvUhVKY7w9Zgxr-0YHWFRd3$l_6UX zpXt^U&TiC*qZWx#pOG6k?3Tg)pra*fw(O6_45>lUBN1U5Qmc>^DHt)5b~Ntjsw!NI z1n4{$HWFeIi)*qvgK^ui;(81VQc1(wJ8C#tjR>Dkjf{xYC^_B^#qrdCc)uZxtgua6 zk98UGQF|;;k`c+0_z)tQ&9DwLB~&12@D1!*mTz_!3Mp=cg;B7Oq4cKN>5v&dW7q@H zal=g6Ipe`siZN4NZiBrkJCU*x216gmbV(FymgHuG@%%|8sgD?gR&0*{y4n=pukZnd z4=Nl~_>jVfbIehu)pG)WvuUpLR}~OKlW|)=S738Wh^a&L+Vx~KJU25o6%G7+Cy5mB zgmYsgkBC|@K4Jm_PwPoz`_|5QSk}^p`XV`649#jr4Lh^Q>Ne~#6Cqxn$7dNMF=%Va z%z9Ef6QmfoXAlQ3)PF8#3Y% zadcE<1`fd1&Q9fMZZnyI;&L;YPuy#TQ8b>AnXr*SGY&xUb>2678A+Y z8K%HOdgq_4LRFu_M>Ou|kj4W%sPPaV)#zDzN~25klE!!PFz_>5wCxglj7WZI13U5| zEq_YLKPH;v8sEhyG`dV_jozR);a6dBvkauhC;1dk%mr+J*Z6MMH9jqxFk@)&h{mHl zrf^i_d-#mTF=6-T8Rk?(1+rPGgl$9=j%#dkf@x6>czSc`jk7$f!9SrV{do%m!t8{? z_iAi$Qe&GDR#Nz^#uJ>-_?(E$ns)(3)X3cYY)?gFvU+N>nnCoBSmwB2<4L|xH19+4 z`$u#*Gt%mRw=*&|em}h_Y`Pzno?k^8e*hEwfM`A_yz-#vJtUfkGb=s>-!6cHfR$Mz z`*A8jVcz7T{n8M>ZTb_sl{EZ9Ctau4naX7TX?&g^VLE?wZ+}m)=YW4ODRy*lV4%-0 zG1XrPs($mVVfpnqoSihnIFkLdxG9um&n-U|`47l{bnr(|8dmglO7H~yeK7-wDwZXq zaHT($Qy2=MMuj@lir(iyxI1HnMlaJwpX86je}e=2n|Esb6hB?SmtDH3 z2qH6o`33b{;M{mDa5@@~1or8+Zcio*97pi1Jkx6v5MXCaYsb~Ynq)eWpKnF{n)FXZ z?Xd;o7ESu&rtMFr5(yJ(B7V>&0gnDdL*4MZH&eO+r*t!TR98ssbMRaw`7;`SLI8mT z=)hSAt~F=mz;JbDI6g~J%w!;QI(X14AnOu;uve^4wyaP3>(?jSLp+LQ7uU(iib%IyB(d&g@+hg;78M>h7yAeq$ALRoHGkKXA+E z$Sk-hd$Fs2nL4w9p@O*Y$c;U)W#d~)&8Js;i^Dp^* z0*7*zEGj~VehF4sRqSGny*K_CxeF=T^8;^lb}HF125G{kMRV?+hYktZWfNA^Mp7y8 zK~Q?ycf%rr+wgLaHQ|_<6z^eTG7izr@99SG9Q{$PCjJabSz`6L_QJJe7{LzTc$P&pwTy<&3RRUlSHmK;?}=QAhQaDW3#VWcNAH3 zeBPRTDf3?3mfdI$&WOg(nr9Gyzg`&u^o!f2rKJ57D_>p z6|?Vg?h(@(*X=o071{g^le>*>qSbVam`o}sAK8>b|11%e&;%`~b2OP7--q%0^2YDS z`2M`{2QYr1VC)sIW9WOu8<~7Q>^$*Og{KF+kI;wFegvaIDkB%3*%PWtWKSq7l`1YcDxQQ2@nv{J!xWV?G+w6C zhUUxUYVf%(Q(40_xrZB@rbxL=Dj3RV^{*yHd>4n-TOoHVRnazDOxxkS9kiZyN}IN3 zB^5N=* zRSTO+rA<{*P8-$GZdyUNOB=MzddG$*@q>mM;pUIiQ_z)hbE#Ze-IS)9G}Rt$5PSB{ zZZ;#h9nS7Rf1ecW&n(Gpu9}{vXQZ-f`UHIvD?cTbF`YvH*{rgE(zE22pLAQfhg-`U zuh612EpByB(~{w7svCylrBk%5$LCIyuhrGi=yOfca`=8ltKxHcSNfDRt@62QH^R_0 z&eQL6rRk>Dvf6rjMQv5ZXzg}S`HqV69hJT^pPHtdhqsrPJWs|IT9>BvpQa@*(FX6v zG}TYjreQCnH(slMt5{NgUf)qsS1F&Bb(M>$X}tWI&yt2I&-rJbqveuj?5J$`Dyfa2 z)m6Mq0XH@K)Y2v8X=-_4=4niodT&Y7W?$KLQhjA<+R}WTdYjX9>kD+SRS^oOY1{A= zZTId-(@wF^UEWso($wZtrs%e7t<}YaC_;#@`r0LUzKY&|qPJz*y~RHG`E6bypP5AX zN!p0^AUu8uDR>xM-ALFzBxXM~Q3z=}fHWCIG>0&I6x2Iu7&U)49j7qeMI&?qb$=4I zdMmhAJrO%@0f%YW! z^gLByEGSk+R0v4*d4w*N$Ju6z#j%HBI}6y$2en=-@S3=6+yZX94m&1j@s- z7T6|#0$c~dYq9IkA!P)AGkp~S$zYJ1SXZ#RM0|E~Q0PSm?DsT4N3f^)b#h(u9%_V5 zX*&EIX|gD~P!vtx?ra71pl%v)F!W~X2hcE!h8cu@6uKURdmo1-7icN4)ej4H1N~-C zjXgOK+mi#aJv4;`DZ%QUbVVZclkx;9`2kgbAhL^d{@etnm+5N8pB#fyH)bxtZGCAv z(%t0kPgBS{Q2HtjrfI0B$$M0c?{r~2T=zeXo7V&&aprCzww=i*}Atu7g^(*ivauMz~kkB%Vt{Wydlz%%2c26%>0PAbZO zVHx%tK(uzDl#ZZK`cW8TD2)eD77wB@gum{B2bO_jnqGl~01EF_^jx4Uqu1yfA~*&g zXJ`-N?D-n~5_QNF_5+Un-4&l$1b zVlHFqtluoN85b^C{A==lp#hS9J(npJ#6P4aY41r) zzCmv~c77X5L}H%sj>5t&@0heUDy;S1gSOS>JtH1v-k5l}z2h~i3^4NF6&iMb;ZYVE zMw*0%-9GdbpF1?HHim|4+)Zed=Fk<2Uz~GKc^P(Ig@x0&XuX0<-K(gA*KkN&lY2Xu zG054Q8wbK~$jE32#Ba*Id2vkqmfV{U$Nx9vJ;jeI`X+j1kh7hB8$CBTe@ANmT^tI8 z%U>zrTKuECin-M|B*gy(SPd`(_xvxjUL?s137KOyH>U{z01cBcFFt=Fp%d+BK4U;9 zQG_W5i)JASNpK)Q0wQpL<+Ml#cei41kCHe&P9?>p+KJN>I~`I^vK1h`IKB7k^xi`f z$H_mtr_+@M>C5+_xt%v}{#WO{86J83;VS@Ei3JLtp<*+hsY1oGzo z0?$?OJO$79;{|@aP!fO6t9TJ!?8i&|c&UPWRMbkwT3nEeFH`Yyyh6b%Rm^nBuTt@9 z+$&-4lf!G|@LCo3<8=yN@5dYbc%uq|Hz|0tiiLQKiUoM9g14zyECKGv0}3AWv2WJ zUAXGUhvkNk`0-H%ACsRSmy4fJ@kxBD3ZKSj6g(n1KPw?g{v19phcBr3BEF>J%lL|d zud3LNuL;cR*xS+;X+N^Br+x2{&hDMhb-$6_fKU(Pt0FQUXgNrZvzsVCnsFqv?#L z4-FYsQ-?D>;LdjHu_TT1CHN~aGkmDjWJkJg4G^!+V_APd%_48tErDv6BW5;ji^UDD zRu5Sw7wwplk`w{OGEKWJM&61c-AWn!SeUP8G#+beH4_Ov*)NUV?eGw&GHNDI6G(1Y zTfCv?T*@{QyK|!Q09wbk5koPD>=@(cA<~i4pSO?f(^5sSbdhUc+K$DW#_7^d7i%At z?KBg#vm$?P4h%?T=XymU;w*AsO_tJr)`+HUll+Uk_zx6vNw>G3jT){w3ck+Z=>7f0 zZVkM*!k^Z_E@_pZK6uH#|vzoL{-j1VFlUHP&5~q?j=UvJJNQG ztQdiCF$8_EaN_Pu8+afN6n8?m5UeR_p_6Log$5V(n9^W)-_vS~Ws`RJhQNPb1$C?| zd9D_ePe*`aI9AZ~Ltbg)DZ;JUo@-tu*O7CJ=T)ZI1&tn%#cisS85EaSvpS~c#CN9B z#Bx$vw|E@gm{;cJOuDi3F1#fxWZ9+5JCqVRCz5o`EDW890NUfNCuBn)3!&vFQE{E$L`Cf7FMSSX%ppLH+Z}#=p zSow$)$z3IL7frW#M>Z4|^9T!=Z8}B0h*MrWXXiVschEA=$a|yX9T~o!=%C?T+l^Cc zJx&MB$me(a*@lLLWZ=>PhKs!}#!ICa0! zq%jNgnF$>zrBZ3z%)Y*yOqHbKzEe_P=@<5$u^!~9G2OAzi#}oP&UL9JljG!zf{JIK z++G*8j)K=$#57N)hj_gSA8golO7xZP|KM?elUq)qLS)i(?&lk{oGMJh{^*FgklBY@Xfl<_Q zXP~(}ST6V01$~VfOmD6j!Hi}lsE}GQikW1YmBH)`f_+)KI!t#~B7=V;{F*`umxy#2Wt8(EbQ~ks9wZS(KV5#5Tn3Ia90r{}fI%pfbqBAG zhZ)E7)ZzqA672%@izC5sBpo>dCcpXi$VNFztSQnmI&u`@zQ#bqFd9d&ls?RomgbSh z9a2rjfNiKl2bR!$Y1B*?3Ko@s^L5lQN|i6ZtiZL|w5oq%{Fb@@E*2%%j=bcma{K~9 z*g1%nEZ;0g;S84ZZ$+Rfurh;Nhq0;{t~(EIRt}D@(Jb7fbe+_@H=t&)I)gPCtj*xI z9S>k?WEAWBmJZ|gs}#{3*pR`-`!HJ)1Dkx8vAM6Tv1bHZhH=MLI;iC#Y!$c|$*R>h zjP{ETat(izXB{@tTOAC4nWNhh1_%7AVaf!kVI5D=Jf5I1!?}stbx_Yv23hLf$iUTb z-)WrTtd2X+;vBW_q*Z6}B!10fs=2FA=3gy*dljsE43!G*3Uw(Is>(-a*5E!T4}b-Y zfvOC)-HYjNfcpi`=kG%(X3XcP?;p&=pz+F^6LKqRom~pA}O* zitR+Np{QZ(D2~p_Jh-k|dL!LPmexLM?tEqI^qRDq9Mg z5XBftj3z}dFir4oScbB&{m5>s{v&U=&_trq#7i&yQN}Z~OIu0}G)>RU*`4<}@7bB% zKYxGx0#L#u199YKSWZwV$nZd>D>{mDTs4qDNyi$4QT6z~D_%Bgf?>3L#NTtvX;?2D zS3IT*2i$Snp4fjDzR#<)A``4|dA(}wv^=L?rB!;kiotwU_gma`w+@AUtkSyhwp{M} z!e`jbUR3AG4XvnBVcyIZht6Vi~?pCC!$XF2 z*V~)DBVm8H7$*OZQJYl3482hadhsI2NCz~_NINtpC?|KI6H3`SG@1d%PsDdw{u}hq zN;OU~F7L1jT&KAitilb&Fl3X12zfSuFm;X)xQWOHL&7d)Q5wgn{78QJ6k5J;is+XP zCPO8_rlGMJB-kuQ*_=Yo1TswG4xnZd&eTjc8=-$6J^8TAa~kEnRQ@Zp-_W&B(4r@F zA==}0vBzsF1mB~743XqBmL9=0RSkGn$cvHf*hyc{<2{@hW+jKjbC|y%CNupHY_NC% zivz^btBLP-cDyV8j>u)=loBs>HoI5ME)xg)oK-Q0wAy|8WD$fm>K{-`0|W{H00;;G z000j`0OWQ8aHA9e04^;603eeQIvtaXMG=2tcr1y8Fl-J;AS+=<0%DU8Bp3oEEDhA^ zOY)M8%o5+cF$rC?trfMcty*f)R;^v=f~}||Xe!#;T3eTDZELN&-50xk+J1heP5AQ>h5O#S_uO;O@;~REd*_G$x$hVeE#bchX)otXQy|S5(oB)2a2%Sc(iDHm z=d>V|a!BLp9^#)o7^EQ2kg=K4%nI^sK2w@-kmvB+ARXYdq?xC2age6)e4$^UaY=wn zgLD^{X0A+{ySY+&7RpldwpC6=E zSPq?y(rl8ZN%(A*sapd4PU+dIakIwT0=zxIJEUW0kZSo|(zFEWdETY*ZjIk9uNMUA ze11=mHu8lUUlgRx!hItf0dAF#HfdIB+#aOuY--#QN9Ry zbx|XkG?PrBb@l6Owl{9Oa9w{x^R}%GwcEEfY;L-6OU8|9RXvu`-ECS`jcO1x1MP{P zcr;Bw##*Dod9K@pEx9z9G~MiNi>8v1OU-}vk*HbI)@CM? zn~b=jWUF%HP=CS+VCP>GiAU_UOz$aq3%%Z2laq^Gx`WAEmuNScCN)OlW>YHGYFgV2 z42lO5ZANs5VMXLS-RZTvBJkWy*OeV#L;7HwWg51*E|RpFR=H}h(|N+79g)tIW!RBK ze08bg^hlygY$C2`%N>7bDm`UZ(5M~DTanh3d~dg+OcNdUanr8azO?})g}EfnUB;5- zE1FX=ru?X=zAk4_6@__o1fE+ml1r&u^f1Kb24Jf-)zKla%-dbd>UZ1 zrj3!RR!Jg`ZnllKJ)4Yfg)@z>(fFepeOcp=F-^VHv?3jSxfa}-NB~*qkJ5Uq(yn+( z<8)qbZh{C!xnO@-XC~XMNVnr-Z+paowv!$H7>`ypMwA(X4(knx7z{UcWWe-wXM!d? zYT}xaVy|7T@yCbNOoy)$D=E%hUNTm(lPZqL)?$v+-~^-1P8m@Jm2t^L%4#!JK#Vtg zyUjM+Y*!$);1<)0MUqL00L0*EZcsE&usAK-?|{l|-)b7|PBKl}?TM6~#j9F+eZq25_L&oSl}DOMv^-tacpDI)l*Ws3u+~jO@;t(T)P=HCEZ#s_5q=m zOsVY!QsOJn)&+Ge6Tm)Ww_Bd@0PY(78ZJ)7_eP-cnXYk`>j9q`x2?Xc6O@55wF+6R zUPdIX!2{VGA;FSivN@+;GNZ7H2(pTDnAOKqF*ARg+C54vZ@Ve`i?%nDDvQRh?m&`1 zq46gH)wV=;UrwfCT3F(m!Q5qYpa!#f6qr0wF=5b9rk%HF(ITc!*R3wIFaCcftGwPt z(kzx{$*>g5L<;u}HzS4XD%ml zmdStbJcY@pn`!fUmkzJ8N>*8Y+DOO^r}1f4ix-`?x|khoRvF%jiA)8)P{?$8j2_qN zcl3Lm9-s$xdYN9)>3j6BPFK)Jbovl|Sf_p((CHe!4hx@F)hd&&*Xb&{TBj>%pT;-n z{3+hA^QZYnjXxtF2XwxPZ`S#J8h>5qLwtwM-{5abbEnRS z`9_`Zq8FJiI#0syE_V_3M&trw$P=ezkHosV$8&I5c0(*-9KBE5DJOC-Xv zw}1bq~AD0_Xerm`%ryiG9_$S z5G|btfiAUNdV09SO2l9v+e#(H6HYOdQs=^ z@xwZQU)~;p1L*~ciC}9ao{nQ-@B>rpUzKBxv=cUusOP5Trs3QnvHxGh9e>s7AM{V1|HfYe z3QwH;nHHR49fYzuGc3W3l5xrDAI392SFXx>lWE3V9Ds9il3PyZaN5>oC3>9W-^7vC z3~KZ-@iD?tIkhg+6t{m;RGk2%>@I0&kf)o$+-^ls0(YABNbM(=l#ad@nKp_j=b~Xs ziR;xu_+)lxy6|+af!@}gO2H_x)p;nZ-tYxW5Omq=l`GzMp*GTLr>vZN1?e}^C$t*Z zvzEdIc2|HA2RFN_4#EkzMqKnbbw!?!?%B@M0^^5Z;K?x-%lg?Z>}wMV8zEqHZ$cr~Y#Wv>9+)KMUZatUqbRU8 z8t9qrek(H^C0Tuzq|cP2$WL7tzj+Dj5y^2SF1D154CnsB$xbz`$wV||n-cG%rsT$p z+3RHdadK(3-noj(2L#8c5lODg)V8pv(GEnNb@F>dEHQr>!qge@L>#qg)RAUtiOYqF ziiV_ETExwD)bQ<))?-9$)E(FiRBYyC@}issHS!j9n)~I1tarxnQ2LfjdIJ)*jp{0E z&1oTd%!Qbw$W58s!6ms>F z=p0!~_Mv~8jyaicOS*t(ntw`5uFi0Bc4*mH8kSkk$>!f0;FM zX_t14I55!ZVsg0O$D2iuEDb7(J>5|NKW^Z~kzm@dax z9(|As$U7^}LF%#`6r&UPB*6`!Rf74h~*C=ami6xUxYCwiJxdr$+`z zKSC4A%8!s%R&j*2si(OEc*fy!q)?%=TjDZJ2}O zxT6o>jlKXz_7_Y$N})}IG`*#KfMzs#R(SI#)3*ZEzCv%_tu(VTZ5J| zw2$5kK)xTa>xGFgS0?X(NecjzFVKG%VVn?neu=&eQ+DJ1APlY1E?Q1s!Kk=yf7Uho z>8mg_!U{cKqpvI3ucSkC2V`!d^XMDk;>GG~>6>&X_z75-kv0UjevS5ORHV^e8r{tr z-9z*y&0eq3k-&c_AKw~<`8dtjsP0XgFv6AnG?0eo5P14T{xW#b*Hn2gEnt5-KvN1z zy!TUSi>IRbD3u+h@;fn7fy{F&hAKx7dG4i!c?5_GnvYV|_d&F16p;)pzEjB{zL-zr z(0&AZUkQ!(A>ghC5U-)t7(EXb-3)tNgb=z`>8m8n+N?vtl-1i&*ftMbE~0zsKG^I$ zSbh+rUiucsb!Ax@yB}j>yGeiKIZk1Xj!i#K^I*LZW_bWQIA-}FmJ~^}>p=K$bX9F{}z{s^KWc~OK(zl_X57aB^J9v}yQ5h#BE$+C)WOglV)nd0WWtaF{7`_Ur`my>4*NleQG#xae4fIo(b zW(&|g*#YHZNvDtE|6}yHvu(hDekJ-t*f!2RK;FZHRMb*l@Qwkh*~CqQRNLaepXypX z1?%ATf_nHIu3z6gK<7Dmd;{`0a!|toT0ck|TL$U;7Wr-*piO@R)KrbUz8SXO0vr1K z>76arfrqImq!ny+VkH!4?x*IR$d6*;ZA}Mhro(mzUa?agrFZpHi*)P~4~4N;XoIvH z9N%4VK|j4mV2DRQUD!_-9fmfA2(YVYyL#S$B;vqu7fnTbAFMqH``wS7^B5=|1O&fL z)qq(oV6_u4x(I(**#mD}MnAy(C&B4a1n6V%$&=vrIDq^F_KhE5Uw8_@{V`_#M0vCu zaNUXB=n0HT@D+ppDXi8-vp{tj)?7+k>1j}VvEKRgQ~DWva}8*pp`W8~KRo*kJ*&X} zP!~2fxQr@dM*q0dI|)Fux=pZWBk==RI7i{^BQf`kWlD2%|@R9!JA7& zLbM$uJ12y}_62$|T|{)@OJZtzfpL^t@1nMTYHutrF#D+^?~CN~9`YQ@#&&@c_Zf)( zbC~y8!2LO8jHwQXv>G~1q?c68ipT*%dY&c{8wd_!Y#~tMJ7yk!F8| zt?m_CLVw6cU@@p(#h4cY&Qsfz2Xp3w^4Cg%m03Tmq~9n%hyoMH^KY7{(QkRyn_!YB zzZa!Tgr~5$MAG$x)Fs71#6j}Kvcv3=9VUX8CH< zbP3|fY8f#$K*<5JQ7whM(v=GN2k26Xsh)#0!HKS(koLgAp-;)8z0w&_Z=nG4v6n8u z&Tm0Fi){4_!Y5Kp?!zv$FKfUifQ{%c82uYfrvE{%ejUd72aNYmI*0z3-a-EYr+bB->oH3#t(AY3 zV{Z=(SJr;D#0(`u*dc*~9T7D8Pudw894%!>c4wU&V1m<~0InidR6fbi?yPl(z+sKa zdF*kS>_4^1UO>y4T%Ar>epSr5&vp`$KdY7B(F%P0@VyHk@1fJ=6X0=aGjD-)BrOJD zW}IU@hg~^2r>a1fQvjTtvL*mKJ7q;pfP*U2=URL`VB_Y_JojbZ+MS=vaVN0C6L_MV zG1#5=35-E`KsD%r>-Q_ndvJ2tOYcMMP9f*t0iJ`(Z`^+YP)h>@lR(@Wvrt-`0tHG+ zuP2R@@mx=T@fPoQ1s`e^1I0H*kQPBGDky@!ZQG@8jY-+2ihreG5q$6i{3vmDTg0j$ zzRb*-nKN@{_wD`V6+i*YS)?$XfrA-sW?js?SYU8#vXxxQCc|*K!EbpWfu)3~jwq6_@KC0m;3A%jH^18_a0;ksC2DEwa@2{9@{ z9@T??<4QwR69zk{UvcHHX;`ICOwrF;@U;etd@YE)4MzI1WCsadP=`%^B>xPS-{`=~ zZ+2im8meb#4p~XIL9}ZOBg7D8R=PC8V}ObDcxEEK(4yGKcyCQWUe{9jCs+@k!_y|I z%s{W(&>P4w@hjQ>PQL$zY+=&aDU6cWr#hG)BVCyfP)h>@3IG5I2mk;8K>)Ppba*!h z005B=001VF5fT=Y4_ytCUk`sv8hJckqSy&Gc2Jx^WJ$J~08N{il-M$fz_ML$)Cpil z(nOv_nlZB^c4s&&O3h=OLiCz&(|f0 zxWU_-JZy>hxP*gvR>CLnNeQ1~g;6{g#-}AbkIzWR;j=8=6!AHpKQCbjFYxf9h%bov zVi;eNa1>t-<14KERUW>^KwoF+8zNo`Y*WiQwq}3m0_2RYtL9Wmu`JaRaQMQ)`Si^6+VbM`!rH~T?DX2=(n4nT zf`G`(Rpq*pDk*v~wMYPZ@vMNZDMPnxMYmU!lA{Xfo?n=Ibb4y3eyY1@Dut4|Y^ml& zqs$r}jAo=B(Ml>ogeEjyv(E`=kBzPf2uv9TQtO$~bamD#=Tv`lNy(K|w$J2O6jS51 zzZtOCHDWz7W0=L1XDW5WR5mtLGc~W+>*vX5{e~U@rE~?7e>vKU-v8bj;F4#abtcV(3ZtwXo9ia93HiETyQXwW4a-0){;$OU*l` zW^bjkyZTJ6_DL^0}`*)#EZ|2nvKRzMLH9-~@Z6$v#t8Dm%(qpP+DgzNe6d)1q zBqhyF$jJTyYFvl_=a>#I8jhJ)d6SBNPg#xg2^kZ3NX8kQ74ah(Y5Z8mlXyzTD&}Q8 ziY(pj-N-V2f>&hZQJ`Di%wp2fN(I%F@l)3M8GcSdNy+#HuO{$I8NXubRlFkL)cY@b z#`v{}-^hRXEq*8B_cG=%PZvI$eo(|8Wc(2o8L#0_GX9L$1@yV>%7mGk)QTD1R*OvS z4OW;ym1)%k9Bfem0tOqq3yyAUWp&q|LsN!RDnxa|j;>R|Mm2rIv7=tej5GFaa+`#| z;7u9Z_^XV+vD@2hF8Xe63+Qd`oig6S9jX(*DbjzPb*K-H7c^7E-(~!R6E%TrgW;RvG;WS{Ziv*W*a*`9Bb;$Er3?MyF~5GcXv`k>U)n}lwv$Sp+H@IKA5$mKk0g*4Ln{!tfvITeY zzr%8JJ5BdcEYsR9eGzJ4B&$}4FMmbRU6{8{_w7Kl77@PNe7|Bc#c?5(C5&Z=kJ#(oM90D4`rh2S!|^L!P#e#1hkD5@~-- z`63GV0~*rOZSqw7k^#-Y$Q4z3Oa2SPRURqEahB1B^h{7~+p03SwzqL9QU#$3-X zdYtQ?-K5xDAdfomEd6(yPtZ!yY_<35bMedeq`z2JWorljz5-f9<^93HM-$#+acw%9r!JOM%O<|BR`W& zd-%j_?b^q7Kl6{q^N{cg2u;11rFB5EP+oqG9&pHD#_Mo@aNMj;LUvsl&nK(ca(hT( zzFc2oHC6WQv8g7jo+3ZSwK+9G$cvfRnql)?g=XeQ3+LTh3)79nhEle8OqS3T$qn(> z(=5Bg?EWq-ldEywgzXW965%H(9^ik*rH(8dNdkbcS9|ow&_r`X~R^R?B+(oTiMzzlx8KnHqUi z8Rh-)VAnS-CO+3}yxqm8)X+N+uzieFVm-F#syP#M1p5&$wX3MJ8 z+R@grZ*5G^Uh4I@VT=>C4RJNc^~3mx$kS1F{L?3)BzdduD2MZKdu#jNno&f2&d{?` zW(>$oktzY@GO{|Ln~Bt^A4)(%?l-&(Dm!iL#$K_xOyhwAf=K2<+Bom zw7|hl6E5}B$d%n0sfZvfQRy9Fyz2~ z83#=#LaHnf1th^k*p|ux8!!8pfHE!)x*%=_hAddl)P%4h4%&8!5-W#xqqb}c=H(i|wqcIS&oDQ{ zhI7N-$f$ra3=RjPmMh?-IEkJYQ<}R9Z!}wmp$#~Uc%u1oh#TP}wF*kJJmQX2#27kL z_dz(yKufo<=m71bZfLp^Ll#t3(IHkrgMcvx@~om%Ib(h(<$Da7urTI`x|%`wD--sN zJEEa>4DGSEG?0ulkosfj8IMNN4)B=ZtvGG{|4Fp=Xhg!wPNgYzS>{Bp%%Qa+624X@ X49Luk)baa85H9$5YCsTPT`SVRWMtMW diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f371643ee..05679dc3c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0c8..744e882ed 100755 --- a/gradlew +++ b/gradlew @@ -72,7 +72,7 @@ case "`uname`" in Darwin* ) darwin=true ;; - MINGW* ) + MSYS* | MINGW* ) msys=true ;; NONSTOP* ) diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 026c5a625..c3c4c38a1 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -10,7 +10,7 @@ Performance and visualization extensions to MST API. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-13`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-14`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0-dev-13' + implementation 'space.kscience:kmath-ast:0.3.0-dev-14' } ``` **Gradle Kotlin DSL:** @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0-dev-13") + implementation("space.kscience:kmath-ast:0.3.0-dev-14") } ``` diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 8209a0dad..9de7e9980 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -45,8 +45,7 @@ kotlin.sourceSets { jvmMain { dependencies { - implementation("org.ow2.asm:asm:9.1") - implementation("org.ow2.asm:asm-commons:9.1") + implementation("org.ow2.asm:asm-commons:9.2") } } } diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 18a83756d..110529b72 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-13`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-14`. **Gradle:** ```gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0-dev-13' + implementation 'space.kscience:kmath-complex:0.3.0-dev-14' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0-dev-13") + implementation("space.kscience:kmath-complex:0.3.0-dev-14") } ``` diff --git a/kmath-core/README.md b/kmath-core/README.md index 6ca8c8ef8..a563552bb 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-13`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-14`. **Gradle:** ```gradle @@ -25,7 +25,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0-dev-13' + implementation 'space.kscience:kmath-core:0.3.0-dev-14' } ``` **Gradle Kotlin DSL:** @@ -36,6 +36,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0-dev-13") + implementation("space.kscience:kmath-core:0.3.0-dev-14") } ``` diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index 10e7bd606..f88f53000 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-13`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-14`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0-dev-13' + implementation 'space.kscience:kmath-ejml:0.3.0-dev-14' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0-dev-13") + implementation("space.kscience:kmath-ejml:0.3.0-dev-14") } ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 6339782dd..d449b4540 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-13`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-14`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0-dev-13' + implementation 'space.kscience:kmath-for-real:0.3.0-dev-14' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0-dev-13") + implementation("space.kscience:kmath-for-real:0.3.0-dev-14") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 77f55528a..d0beae2c8 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-13`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-14`. **Gradle:** ```gradle @@ -21,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0-dev-13' + implementation 'space.kscience:kmath-functions:0.3.0-dev-14' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0-dev-13") + implementation("space.kscience:kmath-functions:0.3.0-dev-14") } ``` diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md index ef8fcd352..71097771d 100644 --- a/kmath-jafama/README.md +++ b/kmath-jafama/README.md @@ -7,7 +7,7 @@ Integration with [Jafama](https://github.com/jeffhain/jafama). ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.0-dev-13`. +The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.0-dev-14`. **Gradle:** ```gradle @@ -17,7 +17,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-jafama:0.3.0-dev-13' + implementation 'space.kscience:kmath-jafama:0.3.0-dev-14' } ``` **Gradle Kotlin DSL:** @@ -28,7 +28,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-jafama:0.3.0-dev-13") + implementation("space.kscience:kmath-jafama:0.3.0-dev-14") } ``` @@ -66,8 +66,8 @@ Report for benchmark configuration jafamaDouble | Benchmark | Score | |:---------:|:-----:| -|`space.kscience.kmath.benchmarks.JafamaBenchmark.core`|14.296120859512893 ± 0.36462633435888736 ops/s| -|`space.kscience.kmath.benchmarks.JafamaBenchmark.jafama`|11.431566395649781 ± 2.570896777898243 ops/s| -|`space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafama`|11.746020495694117 ± 6.205909559197869 ops/s| +|`space.kscience.kmath.benchmarks.JafamaBenchmark.core`|14.35014650168397 ± 0.9200669832937576 ops/s| +|`space.kscience.kmath.benchmarks.JafamaBenchmark.jafama`|12.048429204455887 ± 1.2882929181842269 ops/s| +|`space.kscience.kmath.benchmarks.JafamaBenchmark.strictJafama`|12.977653357239152 ± 1.4122819627470866 ops/s|