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