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) }