From dd3d38490ae5b1758ae4dff7b138cd866b321f30 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 13 Sep 2023 09:00:56 +0300 Subject: [PATCH] [WIP] refactor features to attributes --- .../kscience/attributes/AttributesBuilder.kt | 6 ++++- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- kmath-ast/build.gradle.kts | 2 +- .../integration/CMGaussRuleIntegrator.kt | 2 +- .../kmath/commons/integration/CMIntegrator.kt | 2 +- .../kmath/integration/GaussIntegrator.kt | 14 +++++------ .../kscience/kmath/integration/Integrand.kt | 14 +++++------ .../integration/MultivariateIntegrand.kt | 17 +++++++++---- .../kmath/integration/SimpsonIntegrator.kt | 8 +++---- .../kmath/integration/SplineIntegrator.kt | 4 ++-- .../kmath/integration/UnivariateIntegrand.kt | 24 ++++++++++++------- kmath-tensors/build.gradle.kts | 2 +- 13 files changed, 57 insertions(+), 42 deletions(-) diff --git a/attributes-kt/src/commonMain/kotlin/space/kscience/attributes/AttributesBuilder.kt b/attributes-kt/src/commonMain/kotlin/space/kscience/attributes/AttributesBuilder.kt index d0aed08c9..79df91c3e 100644 --- a/attributes-kt/src/commonMain/kotlin/space/kscience/attributes/AttributesBuilder.kt +++ b/attributes-kt/src/commonMain/kotlin/space/kscience/attributes/AttributesBuilder.kt @@ -7,8 +7,10 @@ package space.kscience.attributes /** * A safe builder for [Attributes] + * + * @param O type marker of an owner object, for which these attributes are made */ -public class AttributesBuilder internal constructor(private val map: MutableMap, Any>) { +public class TypedAttributesBuilder internal constructor(private val map: MutableMap, Any>) { public constructor() : this(mutableMapOf()) @@ -47,6 +49,8 @@ public class AttributesBuilder internal constructor(private val map: MutableMap< public fun build(): Attributes = Attributes(map) } +public typealias AttributesBuilder = TypedAttributesBuilder + public fun AttributesBuilder( attributes: Attributes, ): AttributesBuilder = AttributesBuilder(attributes.content.toMutableMap()) diff --git a/gradle.properties b/gradle.properties index 2f1a2a030..bcb32fede 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ kotlin.code.style=official kotlin.mpp.stability.nowarn=true kotlin.native.ignoreDisabledTargets=true -toolsVersion=0.14.9-kotlin-1.8.20 +toolsVersion=0.14.9-kotlin-1.9.0 org.gradle.parallel=true org.gradle.workers.max=4 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 15de90249..db9a6b825 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-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 7cdb745f0..fe10716af 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -31,7 +31,7 @@ kscience{ kotlin { js { nodejs { - testTask { + testTask{ useMocha().timeout = "0" } } diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt index 7befc60a3..a3fc49d32 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt @@ -22,7 +22,7 @@ public class CMGaussRuleIntegrator( val integrator: GaussIntegrator = getIntegrator(range) //TODO check performance val res: Double = integrator.integrate(integrand.function) - return integrand.modify { + return integrand.withAttributes { IntegrandValue(res) IntegrandCallsPerformed(integrand.calls + numpoints) } 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 7a807c25f..2cc60fb77 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 @@ -26,7 +26,7 @@ public class CMIntegrator( val range = integrand[IntegrationRange] ?: error("Integration range is not provided") val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive) - return integrand.modify { + return integrand.withAttributes { value(res) IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy) IntegrandRelativeAccuracy(integrator.relativeAccuracy) 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 f0aab2c6c..4753edcd0 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,7 +4,7 @@ */ package space.kscience.kmath.integration -import space.kscience.attributes.AttributesBuilder +import space.kscience.attributes.TypedAttributesBuilder import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.Field import space.kscience.kmath.structures.Buffer @@ -57,7 +57,7 @@ public class GaussIntegrator( override fun process(integrand: UnivariateIntegrand): UnivariateIntegrand = with(algebra) { val f = integrand.function val (points, weights) = buildRule(integrand) - var res = zero + var res: T = zero var c = zero for (i in points.indices) { val x = points[i] @@ -67,7 +67,7 @@ public class GaussIntegrator( c = t - res - y res = t } - return integrand.modify { + return integrand.withAttributes { value(res) IntegrandCallsPerformed(integrand.calls + points.size) } @@ -88,12 +88,12 @@ public val Field.gaussIntegrator: GaussIntegrator get() = GaussI * Integrate using [intervals] segments with Gauss-Legendre rule of [order] order. */ @UnstableKMathAPI -public fun GaussIntegrator.integrate( +public inline fun GaussIntegrator.integrate( range: ClosedRange, order: Int = 10, intervals: Int = 10, - attributesBuilder: AttributesBuilder.() -> Unit, - function: (Double) -> T, + attributesBuilder: TypedAttributesBuilder>.() -> Unit, + noinline function: (Double) -> T, ): 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" } @@ -103,7 +103,7 @@ public fun GaussIntegrator.integrate( (0 until intervals).map { i -> (range.start + rangeSize * i)..(range.start + rangeSize * (i + 1)) to order } ) return process( - UnivariateIntegrand( + UnivariateIntegrand( attributeBuilder = { IntegrationRange(range) GaussIntegratorRuleFactory(GaussLegendreRuleFactory) 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 9e2b8d0d7..d465e87c7 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,10 +5,7 @@ package space.kscience.kmath.integration -import space.kscience.attributes.Attribute -import space.kscience.attributes.AttributeContainer -import space.kscience.attributes.AttributesBuilder -import space.kscience.attributes.SafeType +import space.kscience.attributes.* public interface IntegrandAttribute : Attribute @@ -16,9 +13,10 @@ public interface Integrand : AttributeContainer { public val type: SafeType - public fun modify(block: AttributesBuilder.() -> Unit): Integrand - - public fun withAttribute(attribute: Attribute, value: A): Integrand + /** + * Create a copy of this integrand with a new set of attributes + */ + public fun withAttributes(attributes: Attributes): Integrand public companion object } @@ -32,7 +30,7 @@ public sealed class IntegrandValue private constructor(): IntegrandAttribute< } } -public fun AttributesBuilder.value(value: T) { +public fun TypedAttributesBuilder>.value(value: T) { IntegrandValue.forType().invoke(value) } 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 f8937efd2..2081947ec 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 @@ -14,14 +14,21 @@ public class MultivariateIntegrand( public val function: (Point) -> T, ) : Integrand { - override fun modify(block: AttributesBuilder.() -> Unit): MultivariateIntegrand = - MultivariateIntegrand(type, attributes.modify(block), function) + override fun withAttributes(attributes: Attributes): MultivariateIntegrand = + MultivariateIntegrand(type, attributes, function) - override fun withAttribute(attribute: Attribute, value: A): MultivariateIntegrand = - MultivariateIntegrand(type, attributes.withAttribute(attribute, value), function) } +public fun MultivariateIntegrand.withAttribute( + attribute: Attribute, + value: A, +): MultivariateIntegrand = withAttributes(attributes.withAttribute(attribute, value)) + +public fun MultivariateIntegrand.withAttributes( + block: TypedAttributesBuilder>.() -> Unit, +): MultivariateIntegrand = withAttributes(attributes.modify(block)) + public inline fun MultivariateIntegrand( - attributeBuilder: AttributesBuilder.() -> Unit, + attributeBuilder: TypedAttributesBuilder>.() -> Unit, noinline function: (Point) -> T, ): MultivariateIntegrand = MultivariateIntegrand(safeTypeOf(), Attributes(attributeBuilder), function) 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 16d71a743..c0e4fb394 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 @@ -48,7 +48,7 @@ public class SimpsonIntegrator( val ranges = integrand[UnivariateIntegrandRanges] return if (ranges != null) { val res = algebra.sum(ranges.ranges.map { integrateRange(integrand, it.first, it.second) }) - integrand.modify { + integrand.withAttributes { value(res) IntegrandCallsPerformed(integrand.calls + ranges.ranges.sumOf { it.second }) } @@ -57,7 +57,7 @@ public class SimpsonIntegrator( require(numPoints >= 4) { "Simpson integrator requires at least 4 nodes" } val range = integrand[IntegrationRange] ?: 0.0..1.0 val res = integrateRange(integrand, range, numPoints) - integrand.modify { + integrand.withAttributes { value(res) IntegrandCallsPerformed(integrand.calls + numPoints) } @@ -100,7 +100,7 @@ public object DoubleSimpsonIntegrator : UnivariateIntegrator { val ranges = integrand[UnivariateIntegrandRanges] return if (ranges != null) { val res = ranges.ranges.sumOf { integrateRange(integrand, it.first, it.second) } - integrand.modify { + integrand.withAttributes { value(res) IntegrandCallsPerformed(integrand.calls + ranges.ranges.sumOf { it.second }) } @@ -109,7 +109,7 @@ public object DoubleSimpsonIntegrator : UnivariateIntegrator { require(numPoints >= 4) { "Simpson integrator requires at least 4 nodes" } val range = integrand[IntegrationRange] ?: 0.0..1.0 val res = integrateRange(integrand, range, numPoints) - integrand.modify { + integrand.withAttributes { value(res) IntegrandCallsPerformed(integrand.calls + numPoints) } 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 bbec9ff45..636ca5a74 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 @@ -71,7 +71,7 @@ public class SplineIntegrator>( values ) val res = polynomials.integrate(algebra, number(range.start)..number(range.endInclusive)) - integrand.modify { + integrand.withAttributes { value(res) IntegrandCallsPerformed(integrand.calls + nodes.size) } @@ -99,7 +99,7 @@ public object DoubleSplineIntegrator : UnivariateIntegrator { val values = nodes.mapToBuffer(::Float64Buffer) { integrand.function(it) } val polynomials = interpolator.interpolatePolynomials(nodes, values) val res = polynomials.integrate(Float64Field, range) - return integrand.modify { + return integrand.withAttributes { value(res) IntegrandCallsPerformed(integrand.calls + nodes.size) } 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 a5291152a..6a6d47667 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 @@ -16,15 +16,21 @@ public class UnivariateIntegrand( public val function: (Double) -> T, ) : Integrand { - override fun withAttribute(attribute: Attribute, value: A): UnivariateIntegrand = - UnivariateIntegrand(type, attributes.withAttribute(attribute, value), function) - - override fun modify(block: AttributesBuilder.() -> Unit): UnivariateIntegrand = - UnivariateIntegrand(type, attributes.modify(block), function) + override fun withAttributes(attributes: Attributes): UnivariateIntegrand = + UnivariateIntegrand(type, attributes, function) } +public fun UnivariateIntegrand.withAttribute( + attribute: Attribute, + value: A, +): UnivariateIntegrand = withAttributes(attributes.withAttribute(attribute, value)) + +public fun UnivariateIntegrand.withAttributes( + block: TypedAttributesBuilder>.() -> Unit, +): UnivariateIntegrand = withAttributes(attributes.modify(block)) + public inline fun UnivariateIntegrand( - attributeBuilder: AttributesBuilder.() -> Unit, + attributeBuilder: TypedAttributesBuilder>.() -> Unit, noinline function: (Double) -> T, ): UnivariateIntegrand = UnivariateIntegrand(safeTypeOf(), Attributes(attributeBuilder), function) @@ -52,7 +58,7 @@ public class UnivariateIntegrandRanges(public val ranges: List> -public fun AttributesBuilder.integrationNodes(vararg nodes: Double) { +public fun TypedAttributesBuilder>.integrationNodes(vararg nodes: Double) { UnivariateIntegrationNodes(Float64Buffer(nodes)) } @@ -62,7 +68,7 @@ public fun AttributesBuilder.integrationNodes(vararg nodes: Double) { */ @UnstableKMathAPI public inline fun UnivariateIntegrator.integrate( - attributesBuilder: AttributesBuilder.() -> Unit, + attributesBuilder: TypedAttributesBuilder>.() -> Unit, noinline function: (Double) -> T, ): UnivariateIntegrand = process(UnivariateIntegrand(attributesBuilder, function)) @@ -73,7 +79,7 @@ public inline fun UnivariateIntegrator.integrate( @UnstableKMathAPI public inline fun UnivariateIntegrator.integrate( range: ClosedRange, - attributeBuilder: AttributesBuilder.() -> Unit = {}, + attributeBuilder: TypedAttributesBuilder>.() -> Unit = {}, noinline function: (Double) -> T, ): UnivariateIntegrand { diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts index 2497314f0..8977183da 100644 --- a/kmath-tensors/build.gradle.kts +++ b/kmath-tensors/build.gradle.kts @@ -6,7 +6,7 @@ kscience{ jvm() js { browser { - testTask { + testTask{ useMocha().timeout = "0" } }