Feature/tensors performance #497
@ -19,6 +19,7 @@
|
||||
- Complex power
|
||||
- Separate methods for UInt, Int and Number powers. NaN safety.
|
||||
- Tensorflow prototype
|
||||
- `ValueAndErrorField`
|
||||
|
||||
### Changed
|
||||
- Exponential operations merged with hyperbolic functions
|
||||
@ -50,6 +51,7 @@
|
||||
- Tensor algebra takes read-only structures as input and inherits AlgebraND
|
||||
- `UnivariateDistribution` renamed to `Distribution1D`
|
||||
- Rework of histograms.
|
||||
- `UnivariateFunction` -> `Function1D`, `MultivariateFunction` -> `FunctionND`
|
||||
|
||||
### Deprecated
|
||||
- Specialized `DoubleBufferAlgebra`
|
||||
|
@ -13,7 +13,7 @@ import kotlin.math.pow
|
||||
|
||||
fun main() {
|
||||
//Define a function
|
||||
val function: UnivariateFunction<Double> = { x -> 3 * x.pow(2) + 2 * x + 1 }
|
||||
val function: Function1D<Double> = { x -> 3 * x.pow(2) + 2 * x + 1 }
|
||||
|
||||
//get the result of the integration
|
||||
val result = DoubleField.gaussIntegrator.integrate(0.0..10.0, function = function)
|
||||
|
@ -18,7 +18,7 @@ import space.kscience.plotly.scatter
|
||||
|
||||
@OptIn(UnstablePlotlyAPI::class)
|
||||
fun main() {
|
||||
val function: UnivariateFunction<Double> = { x ->
|
||||
val function: Function1D<Double> = { x ->
|
||||
if (x in 30.0..50.0) {
|
||||
1.0
|
||||
} else {
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
package space.kscience.kmath.operations
|
||||
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.BufferFactory
|
||||
import space.kscience.kmath.structures.DoubleBuffer
|
||||
@ -53,7 +52,7 @@ public interface BufferAlgebra<T, out A : Algebra<T>> : Algebra<Buffer<T>> {
|
||||
*/
|
||||
private inline fun <T, A : Algebra<T>> BufferAlgebra<T, A>.mapInline(
|
||||
buffer: Buffer<T>,
|
||||
crossinline block: A.(T) -> T
|
||||
crossinline block: A.(T) -> T,
|
||||
): Buffer<T> = bufferFactory(buffer.size) { elementAlgebra.block(buffer[it]) }
|
||||
|
||||
/**
|
||||
@ -61,7 +60,7 @@ private inline fun <T, A : Algebra<T>> BufferAlgebra<T, A>.mapInline(
|
||||
*/
|
||||
private inline fun <T, A : Algebra<T>> BufferAlgebra<T, A>.mapIndexedInline(
|
||||
buffer: Buffer<T>,
|
||||
crossinline block: A.(index: Int, arg: T) -> T
|
||||
crossinline block: A.(index: Int, arg: T) -> T,
|
||||
): Buffer<T> = bufferFactory(buffer.size) { elementAlgebra.block(it, buffer[it]) }
|
||||
|
||||
/**
|
||||
@ -70,7 +69,7 @@ private inline fun <T, A : Algebra<T>> BufferAlgebra<T, A>.mapIndexedInline(
|
||||
private inline fun <T, A : Algebra<T>> BufferAlgebra<T, A>.zipInline(
|
||||
l: Buffer<T>,
|
||||
r: Buffer<T>,
|
||||
crossinline block: A.(l: T, r: T) -> T
|
||||
crossinline block: A.(l: T, r: T) -> T,
|
||||
): Buffer<T> {
|
||||
require(l.size == r.size) { "Incompatible buffer sizes. left: ${l.size}, right: ${r.size}" }
|
||||
return bufferFactory(l.size) { elementAlgebra.block(l[it], r[it]) }
|
||||
@ -152,10 +151,11 @@ public val ShortRing.bufferAlgebra: BufferRingOps<Short, ShortRing>
|
||||
public open class BufferFieldOps<T, A : Field<T>>(
|
||||
elementAlgebra: A,
|
||||
bufferFactory: BufferFactory<T>,
|
||||
) : BufferRingOps<T, A>(elementAlgebra, bufferFactory), BufferAlgebra<T, A>, FieldOps<Buffer<T>>, ScaleOperations<Buffer<T>> {
|
||||
) : BufferRingOps<T, A>(elementAlgebra, bufferFactory), BufferAlgebra<T, A>, FieldOps<Buffer<T>>,
|
||||
ScaleOperations<Buffer<T>> {
|
||||
|
||||
override fun add(left: Buffer<T>, right: Buffer<T>): Buffer<T> = zipInline(left, right) { l, r -> l + r }
|
||||
override fun multiply(left: Buffer<T>, right: Buffer<T>): Buffer<T> = zipInline(left, right) { l, r -> l * r }
|
||||
// override fun add(left: Buffer<T>, right: Buffer<T>): Buffer<T> = zipInline(left, right) { l, r -> l + r }
|
||||
// override fun multiply(left: Buffer<T>, right: Buffer<T>): Buffer<T> = zipInline(left, right) { l, r -> l * r }
|
||||
override fun divide(left: Buffer<T>, right: Buffer<T>): Buffer<T> = zipInline(left, right) { l, r -> l / r }
|
||||
|
||||
override fun scale(a: Buffer<T>, value: Double): Buffer<T> = a.map { scale(it, value) }
|
||||
@ -168,7 +168,7 @@ public open class BufferFieldOps<T, A : Field<T>>(
|
||||
public class BufferField<T, A : Field<T>>(
|
||||
elementAlgebra: A,
|
||||
bufferFactory: BufferFactory<T>,
|
||||
override val size: Int
|
||||
override val size: Int,
|
||||
) : BufferFieldOps<T, A>(elementAlgebra, bufferFactory), Field<Buffer<T>>, WithSize {
|
||||
|
||||
override val zero: Buffer<T> = bufferFactory(size) { elementAlgebra.zero }
|
||||
|
@ -7,6 +7,6 @@ package space.kscience.kmath.functions
|
||||
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
|
||||
public typealias UnivariateFunction<T> = (T) -> T
|
||||
public typealias Function1D<T> = (T) -> T
|
||||
|
||||
public typealias MultivariateFunction<T> = (Buffer<T>) -> T
|
||||
public typealias FunctionND<T> = (Buffer<T>) -> T
|
@ -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.stat
|
||||
|
||||
import space.kscience.kmath.operations.Field
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sqrt
|
||||
|
||||
/**
|
||||
* A combination of a random [value] and its [dispersion].
|
||||
*
|
||||
* [dispersion] must be positive.
|
||||
*/
|
||||
public data class ValueAndError(val value: Double, val dispersion: Double) {
|
||||
init {
|
||||
require(dispersion >= 0) { "Dispersion must be non-negative" }
|
||||
}
|
||||
|
||||
val error: Double get() = sqrt(dispersion)
|
||||
}
|
||||
|
||||
/**
|
||||
* An algebra for double value + its error combination. The multiplication assumes linear error propagation
|
||||
*/
|
||||
public object ValueAndErrorField : Field<ValueAndError> {
|
||||
|
||||
override val zero: ValueAndError = ValueAndError(0.0, 0.0)
|
||||
|
||||
override val one: ValueAndError = ValueAndError(1.0, 0.0)
|
||||
|
||||
override fun add(left: ValueAndError, right: ValueAndError): ValueAndError =
|
||||
ValueAndError(left.value + right.value, left.dispersion + right.dispersion)
|
||||
|
||||
override fun ValueAndError.unaryMinus(): ValueAndError =
|
||||
ValueAndError(-value, dispersion)
|
||||
|
||||
//TODO study performance impact of pow(2). On JVM it does not exist: https://stackoverflow.com/questions/29144275/xx-vs-math-powx-2-java-performance
|
||||
|
||||
override fun multiply(left: ValueAndError, right: ValueAndError): ValueAndError {
|
||||
val value = left.value * right.value
|
||||
val dispersion = (left.dispersion / left.value.pow(2) + right.dispersion / right.value.pow(2)) * value.pow(2)
|
||||
return ValueAndError(value, dispersion)
|
||||
}
|
||||
|
||||
override fun divide(left: ValueAndError, right: ValueAndError): ValueAndError {
|
||||
val value = left.value / right.value
|
||||
val dispersion = (left.dispersion / left.value.pow(2) + right.dispersion / right.value.pow(2)) * value.pow(2)
|
||||
return ValueAndError(value, dispersion)
|
||||
}
|
||||
|
||||
override fun scale(a: ValueAndError, value: Double): ValueAndError =
|
||||
ValueAndError(a.value * value, a.dispersion * value.pow(2))
|
||||
}
|
Loading…
Reference in New Issue
Block a user